Browse Source

wizard: do not use on storage object during wallet creation

sqlite_db
ThomasV 6 years ago
parent
commit
d5790ea109
  1. 97
      electrum/base_wizard.py
  2. 12
      electrum/gui/kivy/main_window.py
  3. 7
      electrum/gui/kivy/uix/dialogs/installwizard.py
  4. 20
      electrum/gui/qt/__init__.py
  5. 73
      electrum/gui/qt/installwizard.py
  6. 3
      electrum/plugins/trustedcoin/qt.py
  7. 45
      electrum/plugins/trustedcoin/trustedcoin.py
  8. 14
      electrum/storage.py

97
electrum/base_wizard.py

@ -25,6 +25,7 @@
import os import os
import sys import sys
import copy
import traceback import traceback
from functools import partial from functools import partial
from typing import List, TYPE_CHECKING, Tuple, NamedTuple, Any from typing import List, TYPE_CHECKING, Tuple, NamedTuple, Any
@ -65,12 +66,12 @@ class WizardStackItem(NamedTuple):
class BaseWizard(object): class BaseWizard(object):
def __init__(self, config: SimpleConfig, plugins: Plugins, storage: WalletStorage): def __init__(self, config: SimpleConfig, plugins: Plugins):
super(BaseWizard, self).__init__() super(BaseWizard, self).__init__()
self.config = config self.config = config
self.plugins = plugins self.plugins = plugins
self.storage = storage self.data = {}
self.wallet = None # type: Abstract_Wallet self.pw_args = None
self._stack = [] # type: List[WizardStackItem] self._stack = [] # type: List[WizardStackItem]
self.plugin = None self.plugin = None
self.keystores = [] self.keystores = []
@ -83,7 +84,7 @@ class BaseWizard(object):
def run(self, *args): def run(self, *args):
action = args[0] action = args[0]
args = args[1:] args = args[1:]
storage_data = self.storage.get_all_data() storage_data = copy.deepcopy(self.data)
self._stack.append(WizardStackItem(action, args, storage_data)) self._stack.append(WizardStackItem(action, args, storage_data))
if not action: if not action:
return return
@ -110,7 +111,7 @@ class BaseWizard(object):
stack_item = self._stack.pop() stack_item = self._stack.pop()
# try to undo side effects since we last entered 'previous' frame # try to undo side effects since we last entered 'previous' frame
# FIXME only self.storage is properly restored # 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 # rerun 'previous' frame
self.run(stack_item.action, *stack_item.args) self.run(stack_item.action, *stack_item.args)
@ -118,8 +119,7 @@ class BaseWizard(object):
self._stack = [] self._stack = []
def new(self): def new(self):
name = os.path.basename(self.storage.path) title = _("Create new wallet")
title = _("Create") + ' ' + name
message = '\n'.join([ message = '\n'.join([
_("What kind of wallet do you want to create?") _("What kind of wallet do you want to create?")
]) ])
@ -132,36 +132,35 @@ class BaseWizard(object):
choices = [pair for pair in wallet_kinds if pair[0] in wallet_types] 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) 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 exc = None
def on_finished(): def on_finished():
if exc is None: if exc is None:
self.wallet = Wallet(self.storage)
self.terminate() self.terminate()
else: else:
raise exc raise exc
def do_upgrade(): def do_upgrade():
nonlocal exc nonlocal exc
try: try:
self.storage.upgrade() storage.upgrade()
except Exception as e: except Exception as e:
exc = e exc = e
self.waiting_dialog(do_upgrade, _('Upgrading wallet format...'), on_finished=on_finished) self.waiting_dialog(do_upgrade, _('Upgrading wallet format...'), on_finished=on_finished)
def load_2fa(self): def load_2fa(self):
self.storage.put('wallet_type', '2fa') self.data['wallet_type'] = '2fa'
self.storage.put('use_trustedcoin', True) self.data['use_trustedcoin'] = True
self.plugin = self.plugins.load_plugin('trustedcoin') self.plugin = self.plugins.load_plugin('trustedcoin')
def on_wallet_type(self, choice): def on_wallet_type(self, choice):
self.wallet_type = choice self.data['wallet_type'] = self.wallet_type = choice
if choice == 'standard': if choice == 'standard':
action = 'choose_keystore' action = 'choose_keystore'
elif choice == 'multisig': elif choice == 'multisig':
action = 'choose_multisig' action = 'choose_multisig'
elif choice == '2fa': elif choice == '2fa':
self.load_2fa() self.load_2fa()
action = self.storage.get_action() action = self.plugin.get_action(self.data)
elif choice == 'imported': elif choice == 'imported':
action = 'import_addresses_or_keys' action = 'import_addresses_or_keys'
self.run(action) self.run(action)
@ -169,7 +168,7 @@ class BaseWizard(object):
def choose_multisig(self): def choose_multisig(self):
def on_multisig(m, n): def on_multisig(m, n):
multisig_type = "%dof%d" % (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.n = n
self.run('choose_keystore') self.run('choose_keystore')
self.multisig_dialog(run_next=on_multisig) self.multisig_dialog(run_next=on_multisig)
@ -206,27 +205,24 @@ class BaseWizard(object):
is_valid=v, allow_multi=True, show_wif_help=True) is_valid=v, allow_multi=True, show_wif_help=True)
def on_import(self, text): def on_import(self, text):
# create a temporary wallet and exploit that modifications # text is already sanitized by is_address_list and is_private_keys_list
# will be reflected on self.storage
if keystore.is_address_list(text): if keystore.is_address_list(text):
w = Imported_Wallet(self.storage) self.data['addresses'] = {}
addresses = text.split() for addr in text.split():
good_inputs, bad_inputs = w.import_addresses(addresses, write_to_disk=False) assert bitcoin.is_address(addr)
self.data['addresses'][addr] = {}
elif keystore.is_private_key_list(text): elif keystore.is_private_key_list(text):
self.data['addresses'] = {}
k = keystore.Imported_KeyStore({}) k = keystore.Imported_KeyStore({})
self.storage.put('keystore', k.dump())
w = Imported_Wallet(self.storage)
keys = keystore.get_private_keys(text) keys = keystore.get_private_keys(text)
good_inputs, bad_inputs = w.import_private_keys(keys, None, write_to_disk=False) for pk in keys:
self.keystores.append(w.keystore) 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: else:
return self.terminate() 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') return self.run('create_wallet')
def restore_from_key(self): def restore_from_key(self):
@ -246,7 +242,7 @@ class BaseWizard(object):
k = keystore.from_master_key(text) k = keystore.from_master_key(text)
self.on_keystore(k) 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') title = _('Hardware Keystore')
# check available plugins # check available plugins
supported_plugins = self.plugins.get_hardware_support() supported_plugins = self.plugins.get_hardware_support()
@ -348,7 +344,7 @@ class BaseWizard(object):
xpub = self.plugin.get_xpub(device_info.device.id_, derivation, 'standard', self) xpub = self.plugin.get_xpub(device_info.device.id_, derivation, 'standard', self)
password = keystore.Xpub.get_pubkey_from_xpub(xpub, ()) password = keystore.Xpub.get_pubkey_from_xpub(xpub, ())
try: try:
self.storage.decrypt(password) storage.decrypt(password)
except InvalidPassword: except InvalidPassword:
# try to clear session so that user can type another passphrase # try to clear session so that user can type another passphrase
devmgr = self.plugins.device_manager devmgr = self.plugins.device_manager
@ -539,32 +535,37 @@ class BaseWizard(object):
def on_password(self, password, *, encrypt_storage, def on_password(self, password, *, encrypt_storage,
storage_enc_version=STO_EV_USER_PW, encrypt_keystore): 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: for k in self.keystores:
if k.may_have_password(): if k.may_have_password():
k.update_password(None, password) k.update_password(None, password)
if self.wallet_type == 'standard': 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() keys = self.keystores[0].dump()
self.storage.put('keystore', keys) self.data['keystore'] = keys
self.wallet = Standard_Wallet(self.storage)
self.run('create_addresses')
elif self.wallet_type == 'multisig': elif self.wallet_type == 'multisig':
for i, k in enumerate(self.keystores): for i, k in enumerate(self.keystores):
self.storage.put('x%d/'%(i+1), k.dump()) self.data['x%d/'%(i+1)] = k.dump()
self.storage.write()
self.wallet = Multisig_Wallet(self.storage)
self.run('create_addresses')
elif self.wallet_type == 'imported': elif self.wallet_type == 'imported':
if len(self.keystores) > 0: if len(self.keystores) > 0:
keys = self.keystores[0].dump() keys = self.keystores[0].dump()
self.storage.put('keystore', keys) self.data['keystore'] = keys
self.wallet = Imported_Wallet(self.storage) else:
self.wallet.storage.write() raise BaseException('Unknown wallet type')
self.terminate() 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): def show_xpub_and_add_cosigners(self, xpub):
self.show_xpub_dialog(xpub=xpub, run_next=lambda x: self.run('choose_keystore')) self.show_xpub_dialog(xpub=xpub, run_next=lambda x: self.run('choose_keystore'))

12
electrum/gui/kivy/main_window.py

@ -530,8 +530,9 @@ class ElectrumWindow(App):
else: else:
return '' return ''
def on_wizard_complete(self, wizard, wallet): def on_wizard_complete(self, wizard, storage):
if wallet: # wizard returned a wallet if storage:
wallet = Wallet(storage)
wallet.start_network(self.daemon.network) wallet.start_network(self.daemon.network)
self.daemon.add_wallet(wallet) self.daemon.add_wallet(wallet)
self.load_wallet(wallet) self.load_wallet(wallet)
@ -553,11 +554,10 @@ class ElectrumWindow(App):
self.load_wallet(wallet) self.load_wallet(wallet)
else: else:
def launch_wizard(): def launch_wizard():
storage = WalletStorage(path, manual_upgrades=True) wizard = Factory.InstallWizard(self.electrum_config, self.plugins)
wizard = Factory.InstallWizard(self.electrum_config, self.plugins, storage) wizard.path = path
wizard.bind(on_wizard_complete=self.on_wizard_complete) wizard.bind(on_wizard_complete=self.on_wizard_complete)
action = wizard.storage.get_action() wizard.run('new')
wizard.run(action)
if not ask_if_wizard: if not ask_if_wizard:
launch_wizard() launch_wizard()
else: else:

7
electrum/gui/kivy/uix/dialogs/installwizard.py

@ -25,8 +25,8 @@ from .password_dialog import PasswordDialog
# global Variables # global Variables
is_test = (platform == "linux") 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 = "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" test_xpub = "xpub661MyMwAqRbcEbvVtRRSjqxVnaWVUMewVzMiURAKyYratih4TtBpMypzzefmv8zUNebmNVzB3PojdC5sV2P9bDgMoo9B3SARw1MXUUfU1GL"
Builder.load_string(''' Builder.load_string('''
@ -629,7 +629,7 @@ class WizardKnownOTPDialog(WizardOTPDialogBase):
def abort_wallet_creation(self): def abort_wallet_creation(self):
self._on_release = True self._on_release = True
os.unlink(self.wizard.storage.path) os.unlink(self.path)
self.wizard.terminate() self.wizard.terminate()
self.dismiss() self.dismiss()
@ -972,7 +972,8 @@ class InstallWizard(BaseWizard, Widget):
t.start() t.start()
def terminate(self, **kwargs): 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): def choice_dialog(self, **kwargs):
choices = kwargs['choices'] choices = kwargs['choices']

20
electrum/gui/qt/__init__.py

@ -46,6 +46,7 @@ from electrum.plugin import run_hook
from electrum.base_wizard import GoBack from electrum.base_wizard import GoBack
from electrum.util import (UserCancelled, PrintError, profiler, from electrum.util import (UserCancelled, PrintError, profiler,
WalletFileException, BitcoinException, get_new_wallet_name) WalletFileException, BitcoinException, get_new_wallet_name)
from electrum.wallet import Wallet
from .installwizard import InstallWizard from .installwizard import InstallWizard
@ -227,12 +228,18 @@ class ElectrumGui(PrintError):
else: else:
return return
if not wallet: if not wallet:
wizard = InstallWizard(self.config, self.app, self.plugins, None) wizard = InstallWizard(self.config, self.app, self.plugins)
try: try:
if wizard.select_storage(path, self.daemon.get_wallet): path, storage = wizard.select_storage(path, self.daemon.get_wallet)
wallet = wizard.run_and_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: except UserCancelled:
pass return
except GoBack as e: except GoBack as e:
self.print_error('[start_new_window] Exception caught (GoBack)', e) self.print_error('[start_new_window] Exception caught (GoBack)', e)
except (WalletFileException, BitcoinException) as e: except (WalletFileException, BitcoinException) as e:
@ -243,9 +250,10 @@ class ElectrumGui(PrintError):
return return
finally: finally:
wizard.terminate() wizard.terminate()
if not wallet: # return if wallet creation is not complete
if storage is None or storage.get_action():
return return
wallet = Wallet(storage)
if not self.daemon.get_wallet(wallet.storage.path): if not self.daemon.get_wallet(wallet.storage.path):
# wallet was not in memory # wallet was not in memory
wallet.start_network(self.daemon.network) wallet.start_network(self.daemon.network)

73
electrum/gui/qt/installwizard.py

@ -25,7 +25,7 @@ from .network_dialog import NetworkChoiceLayout
from .util import (MessageBoxMixin, Buttons, icon_path, ChoicesLayout, WWLabel, from .util import (MessageBoxMixin, Buttons, icon_path, ChoicesLayout, WWLabel,
InfoButton) InfoButton)
from .password_dialog import PasswordLayout, PasswordLayoutForHW, PW_NEW 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'\ MSG_ENTER_PASSWORD = _("Choose a password to encrypt your wallet keys.") + '\n'\
+ _("Leave this field empty if you want to disable encryption.") + _("Leave this field empty if you want to disable encryption.")
@ -110,8 +110,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
accept_signal = pyqtSignal() accept_signal = pyqtSignal()
def __init__(self, config, app, plugins, storage): def __init__(self, config, app, plugins):
BaseWizard.__init__(self, config, plugins, storage) BaseWizard.__init__(self, config, plugins)
QDialog.__init__(self, None) QDialog.__init__(self, None)
self.setWindowTitle('Electrum - ' + _('Install Wizard')) self.setWindowTitle('Electrum - ' + _('Install Wizard'))
self.app = app self.app = app
@ -186,8 +186,8 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
vbox.addLayout(hbox2) vbox.addLayout(hbox2)
self.set_layout(vbox, title=_('Electrum wallet')) self.set_layout(vbox, title=_('Electrum wallet'))
self.storage = WalletStorage(path, manual_upgrades=True) self.temp_storage = WalletStorage(path, manual_upgrades=True)
wallet_folder = os.path.dirname(self.storage.path) wallet_folder = os.path.dirname(self.temp_storage.path)
def on_choose(): def on_choose():
path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder)
@ -199,25 +199,25 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
wallet_from_memory = get_wallet_from_daemon(path) wallet_from_memory = get_wallet_from_daemon(path)
try: try:
if wallet_from_memory: if wallet_from_memory:
self.storage = wallet_from_memory.storage self.temp_storage = wallet_from_memory.storage
else: else:
self.storage = WalletStorage(path, manual_upgrades=True) self.temp_storage = WalletStorage(path, manual_upgrades=True)
self.next_button.setEnabled(True) self.next_button.setEnabled(True)
except BaseException: except BaseException:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
self.storage = None self.temp_storage = None
self.next_button.setEnabled(False) self.next_button.setEnabled(False)
if self.storage: if self.temp_storage:
if not self.storage.file_exists(): if not self.temp_storage.file_exists():
msg =_("This file does not exist.") + '\n' \ msg =_("This file does not exist.") + '\n' \
+ _("Press 'Next' to create this wallet, or choose another file.") + _("Press 'Next' to create this wallet, or choose another file.")
pw = False pw = False
elif not wallet_from_memory: 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' \ msg = _("This file is encrypted with a password.") + '\n' \
+ _('Enter your password or choose another file.') + _('Enter your password or choose another file.')
pw = True 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' \ msg = _("This file is encrypted using a hardware device.") + '\n' \
+ _("Press 'Next' to choose device to decrypt.") + _("Press 'Next' to choose device to decrypt.")
pw = False pw = False
@ -242,24 +242,24 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
button.clicked.connect(on_choose) button.clicked.connect(on_choose)
self.name_e.textChanged.connect(on_filename) 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) self.name_e.setText(n)
while True: while True:
if self.loop.exec_() != 2: # 2 = next if self.loop.exec_() != 2: # 2 = next
return raise UserCancelled
if self.storage.file_exists() and not self.storage.is_encrypted(): if self.temp_storage.file_exists() and not self.temp_storage.is_encrypted():
break break
if not self.storage.file_exists(): if not self.temp_storage.file_exists():
break 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: if wallet_from_memory:
return wallet_from_memory return wallet_from_memory
if self.storage.file_exists() and self.storage.is_encrypted(): if self.temp_storage.file_exists() and self.temp_storage.is_encrypted():
if self.storage.is_encrypted_with_user_pw(): if self.temp_storage.is_encrypted_with_user_pw():
password = self.pw_e.text() password = self.pw_e.text()
try: try:
self.storage.decrypt(password) self.temp_storage.decrypt(password)
break break
except InvalidPassword as e: except InvalidPassword as e:
QMessageBox.information(None, _('Error'), str(e)) QMessageBox.information(None, _('Error'), str(e))
@ -268,9 +268,9 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
traceback.print_exc(file=sys.stdout) traceback.print_exc(file=sys.stdout)
QMessageBox.information(None, _('Error'), str(e)) QMessageBox.information(None, _('Error'), str(e))
return return
elif self.storage.is_encrypted_with_hw_device(): elif self.temp_storage.is_encrypted_with_hw_device():
try: 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: except InvalidPassword as e:
QMessageBox.information( QMessageBox.information(
None, _('Error'), None, _('Error'),
@ -282,31 +282,32 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
traceback.print_exc(file=sys.stdout) traceback.print_exc(file=sys.stdout)
QMessageBox.information(None, _('Error'), str(e)) QMessageBox.information(None, _('Error'), str(e))
return return
if self.storage.is_past_initial_decryption(): if self.temp_storage.is_past_initial_decryption():
break break
else: else:
return return
else: else:
raise Exception('Unexpected encryption version') raise Exception('Unexpected encryption version')
return True
def run_and_get_wallet(self): return self.temp_storage.path, self.temp_storage if self.temp_storage.file_exists() else None
path = self.storage.path
if self.storage.requires_split(): def run_upgrades(self, storage):
path = storage.path
if storage.requires_split():
self.hide() self.hide()
msg = _("The wallet '{}' contains multiple accounts, which are no longer supported since Electrum 2.7.\n\n" 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) "Do you want to split your wallet into multiple files?").format(path)
if not self.question(msg): if not self.question(msg):
return 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 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): if self.question(msg):
os.remove(path) os.remove(path)
self.show_warning(_('The file was removed')) self.show_warning(_('The file was removed'))
return return
action = self.storage.get_action() action = storage.get_action()
if action and action not in ('new', 'upgrade_storage'): if action: #< and action not in ('new', 'upgrade_storage'):
self.hide() self.hide()
msg = _("The file '{}' contains an incompletely created wallet.\n" msg = _("The file '{}' contains an incompletely created wallet.\n"
"Do you want to complete its creation now?").format(path) "Do you want to complete its creation now?").format(path)
@ -316,13 +317,15 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
self.show_warning(_('The file was removed')) self.show_warning(_('The file was removed'))
return return
self.show() self.show()
if action: self.data = storage.data
# self.wallet is set in run
self.run(action) 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) if storage.requires_upgrade():
return self.wallet self.upgrade_storage(storage)
def finished(self): def finished(self):
"""Called in hardware client wrapper, in order to close popups.""" """Called in hardware client wrapper, in order to close popups."""

3
electrum/plugins/trustedcoin/qt.py

@ -200,7 +200,7 @@ class Plugin(TrustedCoinPlugin):
def go_online_dialog(self, wizard: InstallWizard): def go_online_dialog(self, wizard: InstallWizard):
msg = [ 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 " _("You need to be online in order to complete the creation of "
"your wallet. If you generated your seed on an offline " "your wallet. If you generated your seed on an offline "
'computer, click on "{}" to close this window, move your ' 'computer, click on "{}" to close this window, move your '
@ -209,6 +209,7 @@ class Plugin(TrustedCoinPlugin):
_('If you are online, click on "{}" to continue.').format(_('Next')) _('If you are online, click on "{}" to continue.').format(_('Next'))
] ]
msg = '\n\n'.join(msg) msg = '\n\n'.join(msg)
wizard.create_storage(wizard.path)
wizard.reset_stack() wizard.reset_stack()
wizard.confirm_dialog(title='', message=msg, run_next = lambda x: wizard.run('accept_terms_of_use')) wizard.confirm_dialog(title='', message=msg, run_next = lambda x: wizard.run('accept_terms_of_use'))

45
electrum/plugins/trustedcoin/trustedcoin.py

@ -578,12 +578,9 @@ class TrustedCoinPlugin(BasePlugin):
def on_password(self, wizard, password, encrypt_storage, k1, k2): def on_password(self, wizard, password, encrypt_storage, k1, k2):
k1.update_password(None, password) k1.update_password(None, password)
wizard.storage.set_keystore_encryption(bool(password)) wizard.data['x1/'] = k1.dump()
if encrypt_storage: wizard.data['x2/'] = k2.dump()
wizard.storage.set_password(password, enc_version=STO_EV_USER_PW) wizard.pw_args = password, encrypt_storage, STO_EV_USER_PW
wizard.storage.put('x1/', k1.dump())
wizard.storage.put('x2/', k2.dump())
wizard.storage.write()
self.go_online_dialog(wizard) self.go_online_dialog(wizard)
def restore_wallet(self, wizard): def restore_wallet(self, wizard):
@ -618,34 +615,26 @@ class TrustedCoinPlugin(BasePlugin):
self.create_keystore(wizard, seed, passphrase) self.create_keystore(wizard, seed, passphrase)
def on_restore_pw(self, wizard, seed, passphrase, password, encrypt_storage): def on_restore_pw(self, wizard, seed, passphrase, password, encrypt_storage):
storage = wizard.storage
xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase) xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase)
k1 = keystore.from_xprv(xprv1) k1 = keystore.from_xprv(xprv1)
k2 = keystore.from_xprv(xprv2) k2 = keystore.from_xprv(xprv2)
k1.add_seed(seed) k1.add_seed(seed)
k1.update_password(None, password) k1.update_password(None, password)
k2.update_password(None, password) k2.update_password(None, password)
storage.put('x1/', k1.dump()) wizard.data['x1/'] = k1.dump()
storage.put('x2/', k2.dump()) wizard.data['x2/'] = k2.dump()
long_user_id, short_id = get_user_id(storage) long_user_id, short_id = get_user_id(wizard.data)
xtype = xpub_type(xpub1) xtype = xpub_type(xpub1)
xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id) xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id)
k3 = keystore.from_xpub(xpub3) k3 = keystore.from_xpub(xpub3)
storage.put('x3/', k3.dump()) wizard.data['x3/'] = k3.dump()
wizard.pw_args = password, encrypt_storage, STO_EV_USER_PW
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()
def create_remote_key(self, email, wizard): def create_remote_key(self, email, wizard):
xpub1 = wizard.storage.get('x1/')['xpub'] xpub1 = wizard.data['x1/']['xpub']
xpub2 = wizard.storage.get('x2/')['xpub'] xpub2 = wizard.data['x2/']['xpub']
# Generate third key deterministically. # 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) xtype = xpub_type(xpub1)
xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id) xpub3 = make_xpub(get_signing_xpub(xtype), long_user_id)
# secret must be sent by the server # secret must be sent by the server
@ -709,16 +698,14 @@ class TrustedCoinPlugin(BasePlugin):
wizard.terminate() wizard.terminate()
else: else:
k3 = keystore.from_xpub(xpub3) k3 = keystore.from_xpub(xpub3)
wizard.storage.put('x3/', k3.dump()) wizard.data['x3/'] = k3.dump()
wizard.storage.put('use_trustedcoin', True) wizard.data['use_trustedcoin'] = True
wizard.storage.write() wizard.terminate()
wizard.wallet = Wallet_2fa(wizard.storage)
wizard.run('create_addresses')
def on_reset_auth(self, wizard, short_id, seed, passphrase, xpub3): def on_reset_auth(self, wizard, short_id, seed, passphrase, xpub3):
xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase) xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase)
if (wizard.storage.get('x1/')['xpub'] != xpub1 or if (wizard.data['x1/']['xpub'] != xpub1 or
wizard.storage.get('x2/')['xpub'] != xpub2): wizard.data['x2/']['xpub'] != xpub2):
wizard.show_message(_('Incorrect seed')) wizard.show_message(_('Incorrect seed'))
return return
r = server.get_challenge(short_id) r = server.get_challenge(short_id)

14
electrum/storage.py

@ -102,20 +102,6 @@ class JsonDB(PrintError):
self.modified = True self.modified = True
self.data.pop(key) 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 @profiler
def write(self): def write(self):
with self.db_lock: with self.db_lock:

Loading…
Cancel
Save