URI: 
       twizard: do not use on storage object during wallet creation - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit d5790ea10994f71d4cd0c01d5a08fe87a1d25b82
   DIR parent d6c2a0af946a7691b226a59aa5e3bcdcd6e31fa7
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sat, 23 Feb 2019 15:59:01 +0100
       
       wizard: do not use on storage object during wallet creation
       
       Diffstat:
         M electrum/base_wizard.py             |      97 ++++++++++++++++---------------
         M electrum/gui/kivy/main_window.py    |      12 ++++++------
         M electrum/gui/kivy/uix/dialogs/inst… |       7 ++++---
         M electrum/gui/qt/__init__.py         |      20 ++++++++++++++------
         M electrum/gui/qt/installwizard.py    |      73 ++++++++++++++++---------------
         M electrum/plugins/trustedcoin/qt.py  |       3 ++-
         M electrum/plugins/trustedcoin/trust… |      45 +++++++++++--------------------
         M electrum/storage.py                 |      14 --------------
       
       8 files changed, 129 insertions(+), 142 deletions(-)
       ---
   DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
       t@@ -25,6 +25,7 @@
        
        import os
        import sys
       +import copy
        import traceback
        from functools import partial
        from typing import List, TYPE_CHECKING, Tuple, NamedTuple, Any
       t@@ -65,12 +66,12 @@ class WizardStackItem(NamedTuple):
        
        class BaseWizard(object):
        
       -    def __init__(self, config: SimpleConfig, plugins: Plugins, storage: WalletStorage):
       +    def __init__(self, config: SimpleConfig, plugins: Plugins):
                super(BaseWizard, self).__init__()
                self.config = config
                self.plugins = plugins
       -        self.storage = storage
       -        self.wallet = None  # type: Abstract_Wallet
       +        self.data = {}
       +        self.pw_args = None
                self._stack = []  # type: List[WizardStackItem]
                self.plugin = None
                self.keystores = []
       t@@ -83,7 +84,7 @@ class BaseWizard(object):
            def run(self, *args):
                action = args[0]
                args = args[1:]
       -        storage_data = self.storage.get_all_data()
       +        storage_data = copy.deepcopy(self.data)
                self._stack.append(WizardStackItem(action, args, storage_data))
                if not action:
                    return
       t@@ -110,7 +111,7 @@ class BaseWizard(object):
                stack_item = self._stack.pop()
                # try to undo side effects since we last entered 'previous' frame
                # FIXME only self.storage is properly restored
       -        self.storage.overwrite_all_data(stack_item.storage_data)
       +        self.data = copy.deepcopy(stack_item.storage_data)
                # rerun 'previous' frame
                self.run(stack_item.action, *stack_item.args)
        
       t@@ -118,8 +119,7 @@ class BaseWizard(object):
                self._stack = []
        
            def new(self):
       -        name = os.path.basename(self.storage.path)
       -        title = _("Create") + ' ' + name
       +        title = _("Create new wallet")
                message = '\n'.join([
                    _("What kind of wallet do you want to create?")
                ])
       t@@ -132,36 +132,35 @@ class BaseWizard(object):
                choices = [pair for pair in wallet_kinds if pair[0] in wallet_types]
                self.choice_dialog(title=title, message=message, choices=choices, run_next=self.on_wallet_type)
        
       -    def upgrade_storage(self):
       +    def upgrade_storage(self, storage):
                exc = None
                def on_finished():
                    if exc is None:
       -                self.wallet = Wallet(self.storage)
                        self.terminate()
                    else:
                        raise exc
                def do_upgrade():
                    nonlocal exc
                    try:
       -                self.storage.upgrade()
       +                storage.upgrade()
                    except Exception as e:
                        exc = e
                self.waiting_dialog(do_upgrade, _('Upgrading wallet format...'), on_finished=on_finished)
        
            def load_2fa(self):
       -        self.storage.put('wallet_type', '2fa')
       -        self.storage.put('use_trustedcoin', True)
       +        self.data['wallet_type'] = '2fa'
       +        self.data['use_trustedcoin'] = True
                self.plugin = self.plugins.load_plugin('trustedcoin')
        
            def on_wallet_type(self, choice):
       -        self.wallet_type = choice
       +        self.data['wallet_type'] = self.wallet_type = choice
                if choice == 'standard':
                    action = 'choose_keystore'
                elif choice == 'multisig':
                    action = 'choose_multisig'
                elif choice == '2fa':
                    self.load_2fa()
       -            action = self.storage.get_action()
       +            action = self.plugin.get_action(self.data)
                elif choice == 'imported':
                    action = 'import_addresses_or_keys'
                self.run(action)
       t@@ -169,7 +168,7 @@ class BaseWizard(object):
            def choose_multisig(self):
                def on_multisig(m, n):
                    multisig_type = "%dof%d" % (m, n)
       -            self.storage.put('wallet_type', multisig_type)
       +            self.data['wallet_type'] = multisig_type
                    self.n = n
                    self.run('choose_keystore')
                self.multisig_dialog(run_next=on_multisig)
       t@@ -206,27 +205,24 @@ class BaseWizard(object):
                                     is_valid=v, allow_multi=True, show_wif_help=True)
        
            def on_import(self, text):
       -        # create a temporary wallet and exploit that modifications
       -        # will be reflected on self.storage
       +        # text is already sanitized by is_address_list and is_private_keys_list
                if keystore.is_address_list(text):
       -            w = Imported_Wallet(self.storage)
       -            addresses = text.split()
       -            good_inputs, bad_inputs = w.import_addresses(addresses, write_to_disk=False)
       +            self.data['addresses'] = {}
       +            for addr in text.split():
       +                assert bitcoin.is_address(addr)
       +                self.data['addresses'][addr] = {}
                elif keystore.is_private_key_list(text):
       +            self.data['addresses'] = {}
                    k = keystore.Imported_KeyStore({})
       -            self.storage.put('keystore', k.dump())
       -            w = Imported_Wallet(self.storage)
                    keys = keystore.get_private_keys(text)
       -            good_inputs, bad_inputs = w.import_private_keys(keys, None, write_to_disk=False)
       -            self.keystores.append(w.keystore)
       +            for pk in keys:
       +                assert bitcoin.is_private_key(pk)
       +                txin_type, pubkey = k.import_privkey(pk, None)
       +                addr = bitcoin.pubkey_to_address(txin_type, pubkey)
       +                self.data['addresses'][addr] = {'type':txin_type, 'pubkey':pubkey, 'redeem_script':None}
       +            self.keystores.append(k)
                else:
                    return self.terminate()
       -        if bad_inputs:
       -            msg = "\n".join(f"{key[:10]}... ({msg})" for key, msg in bad_inputs[:10])
       -            if len(bad_inputs) > 10: msg += '\n...'
       -            self.show_error(_("The following inputs could not be imported")
       -                            + f' ({len(bad_inputs)}):\n' + msg)
       -        # FIXME what if len(good_inputs) == 0 ?
                return self.run('create_wallet')
        
            def restore_from_key(self):
       t@@ -246,7 +242,7 @@ class BaseWizard(object):
                k = keystore.from_master_key(text)
                self.on_keystore(k)
        
       -    def choose_hw_device(self, purpose=HWD_SETUP_NEW_WALLET):
       +    def choose_hw_device(self, purpose=HWD_SETUP_NEW_WALLET, storage=None):
                title = _('Hardware Keystore')
                # check available plugins
                supported_plugins = self.plugins.get_hardware_support()
       t@@ -348,7 +344,7 @@ class BaseWizard(object):
                    xpub = self.plugin.get_xpub(device_info.device.id_, derivation, 'standard', self)
                    password = keystore.Xpub.get_pubkey_from_xpub(xpub, ())
                    try:
       -                self.storage.decrypt(password)
       +                storage.decrypt(password)
                    except InvalidPassword:
                        # try to clear session so that user can type another passphrase
                        devmgr = self.plugins.device_manager
       t@@ -539,32 +535,37 @@ class BaseWizard(object):
        
            def on_password(self, password, *, encrypt_storage,
                            storage_enc_version=STO_EV_USER_PW, encrypt_keystore):
       -        assert not self.storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk"
       -        self.storage.set_keystore_encryption(bool(password) and encrypt_keystore)
       -        if encrypt_storage:
       -            self.storage.set_password(password, enc_version=storage_enc_version)
                for k in self.keystores:
                    if k.may_have_password():
                        k.update_password(None, password)
                if self.wallet_type == 'standard':
       -            self.storage.put('seed_type', self.seed_type)
       +            self.data['seed_type'] = self.seed_type
                    keys = self.keystores[0].dump()
       -            self.storage.put('keystore', keys)
       -            self.wallet = Standard_Wallet(self.storage)
       -            self.run('create_addresses')
       +            self.data['keystore'] = keys
                elif self.wallet_type == 'multisig':
                    for i, k in enumerate(self.keystores):
       -                self.storage.put('x%d/'%(i+1), k.dump())
       -            self.storage.write()
       -            self.wallet = Multisig_Wallet(self.storage)
       -            self.run('create_addresses')
       +                self.data['x%d/'%(i+1)] = k.dump()
                elif self.wallet_type == 'imported':
                    if len(self.keystores) > 0:
                        keys = self.keystores[0].dump()
       -                self.storage.put('keystore', keys)
       -            self.wallet = Imported_Wallet(self.storage)
       -            self.wallet.storage.write()
       -            self.terminate()
       +                self.data['keystore'] = keys
       +        else:
       +            raise BaseException('Unknown wallet type')
       +        self.pw_args = password, encrypt_storage, storage_enc_version
       +        self.terminate()
       +
       +    def create_storage(self, path):
       +        if not self.pw_args:
       +            return
       +        password, encrypt_storage, storage_enc_version = self.pw_args
       +        storage = WalletStorage(path)
       +        for key, value in self.data.items():
       +            storage.put(key, value)
       +        storage.set_keystore_encryption(bool(password))# and encrypt_keystore)
       +        if encrypt_storage:
       +            storage.set_password(password, enc_version=storage_enc_version)
       +        storage.write()
       +        return storage
        
            def show_xpub_and_add_cosigners(self, xpub):
                self.show_xpub_dialog(xpub=xpub, run_next=lambda x: self.run('choose_keystore'))
   DIR diff --git a/electrum/gui/kivy/main_window.py b/electrum/gui/kivy/main_window.py
       t@@ -530,8 +530,9 @@ class ElectrumWindow(App):
                else:
                    return ''
        
       -    def on_wizard_complete(self, wizard, wallet):
       -        if wallet:  # wizard returned a wallet
       +    def on_wizard_complete(self, wizard, storage):
       +        if storage:
       +            wallet = Wallet(storage)
                    wallet.start_network(self.daemon.network)
                    self.daemon.add_wallet(wallet)
                    self.load_wallet(wallet)
       t@@ -553,11 +554,10 @@ class ElectrumWindow(App):
                        self.load_wallet(wallet)
                else:
                    def launch_wizard():
       -                storage = WalletStorage(path, manual_upgrades=True)
       -                wizard = Factory.InstallWizard(self.electrum_config, self.plugins, storage)
       +                wizard = Factory.InstallWizard(self.electrum_config, self.plugins)
       +                wizard.path = path
                        wizard.bind(on_wizard_complete=self.on_wizard_complete)
       -                action = wizard.storage.get_action()
       -                wizard.run(action)
       +                wizard.run('new')
                    if not ask_if_wizard:
                        launch_wizard()
                    else:
   DIR diff --git a/electrum/gui/kivy/uix/dialogs/installwizard.py b/electrum/gui/kivy/uix/dialogs/installwizard.py
       t@@ -25,8 +25,8 @@ from .password_dialog import PasswordDialog
        
        # global Variables
        is_test = (platform == "linux")
       -test_seed = "time taxi field recycle tiny license olive virus report rare steel portion achieve"
        test_seed = "grape impose jazz bind spatial mind jelly tourist tank today holiday stomach"
       +test_seed = "time taxi field recycle tiny license olive virus report rare steel portion achieve"
        test_xpub = "xpub661MyMwAqRbcEbvVtRRSjqxVnaWVUMewVzMiURAKyYratih4TtBpMypzzefmv8zUNebmNVzB3PojdC5sV2P9bDgMoo9B3SARw1MXUUfU1GL"
        
        Builder.load_string('''
       t@@ -629,7 +629,7 @@ class WizardKnownOTPDialog(WizardOTPDialogBase):
        
            def abort_wallet_creation(self):
                self._on_release = True
       -        os.unlink(self.wizard.storage.path)
       +        os.unlink(self.path)
                self.wizard.terminate()
                self.dismiss()
        
       t@@ -972,7 +972,8 @@ class InstallWizard(BaseWizard, Widget):
                t.start()
        
            def terminate(self, **kwargs):
       -        self.dispatch('on_wizard_complete', self.wallet)
       +        storage = self.create_storage(self.path)
       +        self.dispatch('on_wizard_complete', storage)
        
            def choice_dialog(self, **kwargs):
                choices = kwargs['choices']
   DIR diff --git a/electrum/gui/qt/__init__.py b/electrum/gui/qt/__init__.py
       t@@ -46,6 +46,7 @@ from electrum.plugin import run_hook
        from electrum.base_wizard import GoBack
        from electrum.util import (UserCancelled, PrintError, profiler,
                                   WalletFileException, BitcoinException, get_new_wallet_name)
       +from electrum.wallet import Wallet
        
        from .installwizard import InstallWizard
        
       t@@ -227,12 +228,18 @@ class ElectrumGui(PrintError):
                    else:
                        return
                if not wallet:
       -            wizard = InstallWizard(self.config, self.app, self.plugins, None)
       +            wizard = InstallWizard(self.config, self.app, self.plugins)
                    try:
       -                if wizard.select_storage(path, self.daemon.get_wallet):
       -                    wallet = wizard.run_and_get_wallet()
       +                path, storage = wizard.select_storage(path, self.daemon.get_wallet)
       +                # storage is None if file does not exist
       +                if storage is None:
       +                    wizard.path = path # needed by trustedcoin plugin
       +                    wizard.run('new')
       +                    storage = wizard.create_storage(path)
       +                else:
       +                    wizard.run_upgrades(storage)
                    except UserCancelled:
       -                pass
       +                return
                    except GoBack as e:
                        self.print_error('[start_new_window] Exception caught (GoBack)', e)
                    except (WalletFileException, BitcoinException) as e:
       t@@ -243,9 +250,10 @@ class ElectrumGui(PrintError):
                        return
                    finally:
                        wizard.terminate()
       -            if not wallet:
       +            # return if wallet creation is not complete
       +            if storage is None or storage.get_action():
                        return
       -
       +            wallet = Wallet(storage)
                    if not self.daemon.get_wallet(wallet.storage.path):
                        # wallet was not in memory
                        wallet.start_network(self.daemon.network)
   DIR diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py
       t@@ -25,7 +25,7 @@ from .network_dialog import NetworkChoiceLayout
        from .util import (MessageBoxMixin, Buttons, icon_path, ChoicesLayout, WWLabel,
                           InfoButton)
        from .password_dialog import PasswordLayout, PasswordLayoutForHW, PW_NEW
       -
       +from electrum.plugin import run_hook
        
        MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\
                             + _("Leave this field empty if you want to disable encryption.")
       t@@ -110,8 +110,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
        
            accept_signal = pyqtSignal()
        
       -    def __init__(self, config, app, plugins, storage):
       -        BaseWizard.__init__(self, config, plugins, storage)
       +    def __init__(self, config, app, plugins):
       +        BaseWizard.__init__(self, config, plugins)
                QDialog.__init__(self, None)
                self.setWindowTitle('Electrum  -  ' + _('Install Wizard'))
                self.app = app
       t@@ -186,8 +186,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                vbox.addLayout(hbox2)
                self.set_layout(vbox, title=_('Electrum wallet'))
        
       -        self.storage = WalletStorage(path, manual_upgrades=True)
       -        wallet_folder = os.path.dirname(self.storage.path)
       +        self.temp_storage = WalletStorage(path, manual_upgrades=True)
       +        wallet_folder = os.path.dirname(self.temp_storage.path)
        
                def on_choose():
                    path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
       t@@ -199,25 +199,25 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                    wallet_from_memory = get_wallet_from_daemon(path)
                    try:
                        if wallet_from_memory:
       -                    self.storage = wallet_from_memory.storage
       +                    self.temp_storage = wallet_from_memory.storage
                        else:
       -                    self.storage = WalletStorage(path, manual_upgrades=True)
       +                    self.temp_storage = WalletStorage(path, manual_upgrades=True)
                        self.next_button.setEnabled(True)
                    except BaseException:
                        traceback.print_exc(file=sys.stderr)
       -                self.storage = None
       +                self.temp_storage = None
                        self.next_button.setEnabled(False)
       -            if self.storage:
       -                if not self.storage.file_exists():
       +            if self.temp_storage:
       +                if not self.temp_storage.file_exists():
                            msg =_("This file does not exist.") + '\n' \
                                  + _("Press 'Next' to create this wallet, or choose another file.")
                            pw = False
                        elif not wallet_from_memory:
       -                    if self.storage.is_encrypted_with_user_pw():
       +                    if self.temp_storage.is_encrypted_with_user_pw():
                                msg = _("This file is encrypted with a password.") + '\n' \
                                      + _('Enter your password or choose another file.')
                                pw = True
       -                    elif self.storage.is_encrypted_with_hw_device():
       +                    elif self.temp_storage.is_encrypted_with_hw_device():
                                msg = _("This file is encrypted using a hardware device.") + '\n' \
                                      + _("Press 'Next' to choose device to decrypt.")
                                pw = False
       t@@ -242,24 +242,24 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
        
                button.clicked.connect(on_choose)
                self.name_e.textChanged.connect(on_filename)
       -        n = os.path.basename(self.storage.path)
       +        n = os.path.basename(self.temp_storage.path)
                self.name_e.setText(n)
        
                while True:
                    if self.loop.exec_() != 2:  # 2 = next
       -                return
       -            if self.storage.file_exists() and not self.storage.is_encrypted():
       +                raise UserCancelled
       +            if self.temp_storage.file_exists() and not self.temp_storage.is_encrypted():
                        break
       -            if not self.storage.file_exists():
       +            if not self.temp_storage.file_exists():
                        break
       -            wallet_from_memory = get_wallet_from_daemon(self.storage.path)
       +            wallet_from_memory = get_wallet_from_daemon(self.temp_storage.path)
                    if wallet_from_memory:
                        return wallet_from_memory
       -            if self.storage.file_exists() and self.storage.is_encrypted():
       -                if self.storage.is_encrypted_with_user_pw():
       +            if self.temp_storage.file_exists() and self.temp_storage.is_encrypted():
       +                if self.temp_storage.is_encrypted_with_user_pw():
                            password = self.pw_e.text()
                            try:
       -                        self.storage.decrypt(password)
       +                        self.temp_storage.decrypt(password)
                                break
                            except InvalidPassword as e:
                                QMessageBox.information(None, _('Error'), str(e))
       t@@ -268,9 +268,9 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                                traceback.print_exc(file=sys.stdout)
                                QMessageBox.information(None, _('Error'), str(e))
                                return
       -                elif self.storage.is_encrypted_with_hw_device():
       +                elif self.temp_storage.is_encrypted_with_hw_device():
                            try:
       -                        self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET)
       +                        self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, self.temp_storage)
                            except InvalidPassword as e:
                                QMessageBox.information(
                                    None, _('Error'),
       t@@ -282,31 +282,32 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                                traceback.print_exc(file=sys.stdout)
                                QMessageBox.information(None, _('Error'), str(e))
                                return
       -                    if self.storage.is_past_initial_decryption():
       +                    if self.temp_storage.is_past_initial_decryption():
                                break
                            else:
                                return
                        else:
                            raise Exception('Unexpected encryption version')
       -        return True
        
       -    def run_and_get_wallet(self):
       -        path = self.storage.path
       -        if self.storage.requires_split():
       +        return self.temp_storage.path, self.temp_storage if self.temp_storage.file_exists() else None
       +
       +    def run_upgrades(self, storage):
       +        path = storage.path
       +        if storage.requires_split():
                    self.hide()
                    msg = _("The wallet '{}' contains multiple accounts, which are no longer supported since Electrum 2.7.\n\n"
                            "Do you want to split your wallet into multiple files?").format(path)
                    if not self.question(msg):
                        return
       -            file_list = '\n'.join(self.storage.split_accounts())
       +            file_list = '\n'.join(storage.split_accounts())
                    msg = _('Your accounts have been moved to') + ':\n' + file_list + '\n\n'+ _('Do you want to delete the old file') + ':\n' + path
                    if self.question(msg):
                        os.remove(path)
                        self.show_warning(_('The file was removed'))
                    return
        
       -        action = self.storage.get_action()
       -        if action and action not in ('new', 'upgrade_storage'):
       +        action = storage.get_action()
       +        if action: #< and action not in ('new', 'upgrade_storage'):
                    self.hide()
                    msg = _("The file '{}' contains an incompletely created wallet.\n"
                            "Do you want to complete its creation now?").format(path)
       t@@ -316,13 +317,15 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
                            self.show_warning(_('The file was removed'))
                        return
                    self.show()
       -        if action:
       -            # self.wallet is set in run
       +            self.data = storage.data
                    self.run(action)
       -            return self.wallet
       +            for k, v in self.data.items():
       +                storage.put(k, v)
       +            storage.write()
       +            return
        
       -        self.wallet = Wallet(self.storage)
       -        return self.wallet
       +        if storage.requires_upgrade():
       +            self.upgrade_storage(storage)
        
            def finished(self):
                """Called in hardware client wrapper, in order to close popups."""
   DIR diff --git a/electrum/plugins/trustedcoin/qt.py b/electrum/plugins/trustedcoin/qt.py
       t@@ -200,7 +200,7 @@ class Plugin(TrustedCoinPlugin):
        
            def go_online_dialog(self, wizard: InstallWizard):
                msg = [
       -            _("Your wallet file is: {}.").format(os.path.abspath(wizard.storage.path)),
       +            _("Your wallet file is: {}.").format(os.path.abspath(wizard.path)),
                    _("You need to be online in order to complete the creation of "
                      "your wallet.  If you generated your seed on an offline "
                      'computer, click on "{}" to close this window, move your '
       t@@ -209,6 +209,7 @@ class Plugin(TrustedCoinPlugin):
                    _('If you are online, click on "{}" to continue.').format(_('Next'))
                ]
                msg = '\n\n'.join(msg)
       +        wizard.create_storage(wizard.path)
                wizard.reset_stack()
                wizard.confirm_dialog(title='', message=msg, run_next = lambda x: wizard.run('accept_terms_of_use'))
        
   DIR diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py
       t@@ -578,12 +578,9 @@ class TrustedCoinPlugin(BasePlugin):
        
            def on_password(self, wizard, password, encrypt_storage, k1, k2):
                k1.update_password(None, password)
       -        wizard.storage.set_keystore_encryption(bool(password))
       -        if encrypt_storage:
       -            wizard.storage.set_password(password, enc_version=STO_EV_USER_PW)
       -        wizard.storage.put('x1/', k1.dump())
       -        wizard.storage.put('x2/', k2.dump())
       -        wizard.storage.write()
       +        wizard.data['x1/'] = k1.dump()
       +        wizard.data['x2/'] = k2.dump()
       +        wizard.pw_args = password, encrypt_storage, STO_EV_USER_PW
                self.go_online_dialog(wizard)
        
            def restore_wallet(self, wizard):
       t@@ -618,34 +615,26 @@ class TrustedCoinPlugin(BasePlugin):
                    self.create_keystore(wizard, seed, passphrase)
        
            def on_restore_pw(self, wizard, seed, passphrase, password, encrypt_storage):
       -        storage = wizard.storage
                xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase)
                k1 = keystore.from_xprv(xprv1)
                k2 = keystore.from_xprv(xprv2)
                k1.add_seed(seed)
                k1.update_password(None, password)
                k2.update_password(None, password)
       -        storage.put('x1/', k1.dump())
       -        storage.put('x2/', k2.dump())
       -        long_user_id, short_id = get_user_id(storage)
       +        wizard.data['x1/'] = k1.dump()
       +        wizard.data['x2/'] = k2.dump()
       +        long_user_id, short_id = get_user_id(wizard.data)
                xtype = xpub_type(xpub1)
                xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id)
                k3 = keystore.from_xpub(xpub3)
       -        storage.put('x3/', k3.dump())
       -
       -        storage.set_keystore_encryption(bool(password))
       -        if encrypt_storage:
       -            storage.set_password(password, enc_version=STO_EV_USER_PW)
       -
       -        wizard.wallet = Wallet_2fa(storage)
       -        wizard.create_addresses()
       -
       +        wizard.data['x3/'] = k3.dump()
       +        wizard.pw_args = password, encrypt_storage, STO_EV_USER_PW
        
            def create_remote_key(self, email, wizard):
       -        xpub1 = wizard.storage.get('x1/')['xpub']
       -        xpub2 = wizard.storage.get('x2/')['xpub']
       +        xpub1 = wizard.data['x1/']['xpub']
       +        xpub2 = wizard.data['x2/']['xpub']
                # Generate third key deterministically.
       -        long_user_id, short_id = get_user_id(wizard.storage)
       +        long_user_id, short_id = get_user_id(wizard.data)
                xtype = xpub_type(xpub1)
                xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id)
                # secret must be sent by the server
       t@@ -709,16 +698,14 @@ class TrustedCoinPlugin(BasePlugin):
                    wizard.terminate()
                else:
                    k3 = keystore.from_xpub(xpub3)
       -            wizard.storage.put('x3/', k3.dump())
       -            wizard.storage.put('use_trustedcoin', True)
       -            wizard.storage.write()
       -            wizard.wallet = Wallet_2fa(wizard.storage)
       -            wizard.run('create_addresses')
       +            wizard.data['x3/'] = k3.dump()
       +            wizard.data['use_trustedcoin'] = True
       +            wizard.terminate()
        
            def on_reset_auth(self, wizard, short_id, seed, passphrase, xpub3):
                xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase)
       -        if (wizard.storage.get('x1/')['xpub'] != xpub1 or
       -                wizard.storage.get('x2/')['xpub'] != xpub2):
       +        if (wizard.data['x1/']['xpub'] != xpub1 or
       +                wizard.data['x2/']['xpub'] != xpub2):
                    wizard.show_message(_('Incorrect seed'))
                    return
                r = server.get_challenge(short_id)
   DIR diff --git a/electrum/storage.py b/electrum/storage.py
       t@@ -102,20 +102,6 @@ class JsonDB(PrintError):
                        self.modified = True
                        self.data.pop(key)
        
       -    def get_all_data(self) -> dict:
       -        with self.db_lock:
       -            return copy.deepcopy(self.data)
       -
       -    def overwrite_all_data(self, data: dict) -> None:
       -        try:
       -            json.dumps(data, cls=util.MyEncoder)
       -        except:
       -            self.print_error(f"json error: cannot save {repr(data)}")
       -            return
       -        with self.db_lock:
       -            self.modified = True
       -            self.data = copy.deepcopy(data)
       -
            @profiler
            def write(self):
                with self.db_lock: