electrum

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

commit 62868ab29a785d9b03b1d13c409d925c6b2d340b
parent 3d9f321cae28f5806e5d75d9032d3c89a7459dd2
Author: ThomasV <thomasv@electrum.org>
Date:   Tue,  5 Jan 2016 13:51:03 +0100

Register loaded wallets in daemon, to prevent a wallet from being opened twice.
Simplify the wizard logic.

Diffstat:
Melectrum | 9+++++----
Mgui/android.py | 2+-
Mgui/gtk.py | 4++--
Mgui/kivy/__init__.py | 2+-
Mgui/qt/__init__.py | 13++++++-------
Mgui/qt/installwizard.py | 17++++++++++++++++-
Mgui/stdio.py | 2+-
Mgui/text.py | 2+-
Mlib/daemon.py | 27++++++++++++++-------------
Mlib/wizard.py | 75+++++++++++++++++++++++++++++++--------------------------------------------
10 files changed, 78 insertions(+), 75 deletions(-)

diff --git a/electrum b/electrum @@ -98,12 +98,12 @@ def prompt_password(prompt, confirm=True): -def init_gui(config, network, plugins): +def init_gui(config, network, daemon, plugins): gui_name = config.get('gui', 'qt') if gui_name in ['lite', 'classic']: gui_name = 'qt' gui = __import__('electrum_gui.' + gui_name, fromlist=['electrum_gui']) - gui = gui.ElectrumGui(config, network, plugins) + gui = gui.ElectrumGui(config, network, daemon, plugins) return gui @@ -343,9 +343,10 @@ if __name__ == '__main__': plugins.start() else: network = None - gui = init_gui(config, network, plugins) - daemon = Daemon(config, network, gui) + daemon = Daemon(config, network) daemon.start() + gui = init_gui(config, network, daemon, plugins) + daemon.gui = gui gui.main() sys.exit(0) diff --git a/gui/android.py b/gui/android.py @@ -904,7 +904,7 @@ config = None class ElectrumGui: - def __init__(self, _config, _network, plugins): + def __init__(self, _config, _network, daemon, plugins): global wallet, network, contacts, config network = _network config = _config diff --git a/gui/gtk.py b/gui/gtk.py @@ -1189,7 +1189,7 @@ class ElectrumWindow: tooltip = tx_hash + "\n%d confirmations"%conf if tx_hash else '' details = self.get_tx_details(tx_hash) - self.history_list.prepend( [tx_hash, conf_icon, time_str, label, is_default_label, + self.history_list.prepend( [tx_hash, conf_icon, time_str, label, False, format_satoshis(value,True,self.num_zeros, whitespaces=True), format_satoshis(balance,False,self.num_zeros, whitespaces=True), tooltip, details] ) if cursor: self.history_treeview.set_cursor( cursor ) @@ -1284,7 +1284,7 @@ class ElectrumWindow: class ElectrumGui(): - def __init__(self, config, network, plugins): + def __init__(self, config, network, daemon, plugins): self.network = network self.config = config diff --git a/gui/kivy/__init__.py b/gui/kivy/__init__.py @@ -35,7 +35,7 @@ from main_window import ElectrumWindow class ElectrumGui: - def __init__(self, config, network, plugins, app=None): + def __init__(self, config, network, daemon, plugins): Logger.debug('ElectrumGUI: initialising') self.network = network self.config = config diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py @@ -66,7 +66,7 @@ class OpenFileEventFilter(QObject): class ElectrumGui(MessageBoxMixin): - def __init__(self, config, network, plugins): + def __init__(self, config, network, daemon, plugins): set_language(config.get('language')) # Uncomment this call to verify objects are being properly # GC-ed when windows are closed @@ -74,6 +74,7 @@ class ElectrumGui(MessageBoxMixin): # ElectrumWindow], interval=5)]) self.network = network self.config = config + self.daemon = daemon self.plugins = plugins self.windows = [] self.efilter = OpenFileEventFilter(self.windows) @@ -134,12 +135,10 @@ class ElectrumGui(MessageBoxMixin): # Use a signal as can be called from daemon thread self.app.emit(SIGNAL('new_window'), path, uri) - def create_window_for_wallet(self, wallet, task): + def create_window_for_wallet(self, wallet): w = ElectrumWindow(self, wallet) self.windows.append(w) self.build_tray_menu() - if task: - WaitingDialog(w, task[0], task[1]) # FIXME: Remove in favour of the load_wallet hook run_hook('on_new_window', w) return w @@ -153,10 +152,10 @@ class ElectrumGui(MessageBoxMixin): break else: wizard = InstallWizard(self.config, self.app, self.plugins) - result = wizard.open_wallet(self.network, path) - if not result: + wallet = self.daemon.load_wallet(path, wizard) + if not wallet: return - w = self.create_window_for_wallet(*result) + w = self.create_window_for_wallet(wallet) if uri: w.pay_to_URI(uri) diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py @@ -17,7 +17,8 @@ from electrum.mnemonic import prepare_seed from electrum.wizard import (WizardBase, UserCancelled, MSG_ENTER_PASSWORD, MSG_RESTORE_PASSPHRASE, MSG_COSIGNER, MSG_ENTER_SEED_OR_MPK, - MSG_SHOW_MPK, MSG_VERIFY_SEED) + MSG_SHOW_MPK, MSG_VERIFY_SEED, + MSG_GENERATING_WAIT) class CosignWidget(QWidget): size = 120 @@ -134,6 +135,20 @@ class InstallWizard(WindowModalDialog, WizardBase): if self.config.get('server') is None: self.network_dialog(network) + def show_restore(self, wallet, network, action): + def on_finished(b): + if action == 'restore': + if network: + if wallet.is_found(): + msg = _("Recovery successful") + else: + msg = _("No transactions found for this seed") + else: + msg = _("This wallet was restored offline. It may " + "contain more addresses than displayed.") + self.show_message(msg) + WaitingDialog(self, MSG_GENERATING_WAIT, wallet.wait_until_synchronized, on_finished) + def set_layout(self, layout): w = QWidget() w.setLayout(layout) diff --git a/gui/stdio.py b/gui/stdio.py @@ -12,7 +12,7 @@ import sys, getpass, datetime class ElectrumGui: - def __init__(self, config, network, plugins): + def __init__(self, config, network, daemon, plugins): self.network = network self.config = config storage = WalletStorage(config.get_wallet_path()) diff --git a/gui/text.py b/gui/text.py @@ -12,7 +12,7 @@ import tty, sys class ElectrumGui: - def __init__(self, config, network, plugins): + def __init__(self, config, network, daemon, plugins): self.config = config self.network = network diff --git a/lib/daemon.py b/lib/daemon.py @@ -61,16 +61,13 @@ class RequestHandler(SimpleJSONRPCRequestHandler): class Daemon(DaemonThread): - def __init__(self, config, network, gui=None): + def __init__(self, config, network): DaemonThread.__init__(self) self.config = config self.network = network - self.gui = gui + self.gui = None self.wallets = {} - if gui is None: - self.wallet = self.load_wallet(config) - else: - self.wallet = None + self.wallet = None self.cmd_runner = Commands(self.config, self.wallet, self.network) host = config.get('rpchost', 'localhost') port = config.get('rpcport', 0) @@ -123,22 +120,26 @@ class Daemon(DaemonThread): response = "Error: Electrum is running in daemon mode. Please stop the daemon first." return response - def load_wallet(self, config): - path = config.get_wallet_path() + def load_wallet(self, path, wizard=None): if path in self.wallets: wallet = self.wallets[path] else: - storage = WalletStorage(path) - wallet = Wallet(storage) - wallet.start_threads(self.network) - self.wallets[path] = wallet + if wizard: + wallet = wizard.open_wallet(self.network, path) + else: + storage = WalletStorage(path) + wallet = Wallet(storage) + wallet.start_threads(self.network) + if wallet: + self.wallets[path] = wallet return wallet def run_cmdline(self, config_options): config = SimpleConfig(config_options) cmdname = config.get('cmd') cmd = known_commands[cmdname] - wallet = self.load_wallet(config) if cmd.requires_wallet else None + path = config.get_wallet_path() + wallet = self.load_wallet(path) if cmd.requires_wallet else None # arguments passed to function args = map(lambda x: config.get(x), cmd.params) # decode json arguments diff --git a/lib/wizard.py b/lib/wizard.py @@ -126,43 +126,9 @@ class WizardBase(PrintError): """Choose a server if one is not set in the config anyway.""" raise NotImplementedError - def open_existing_wallet(self, storage, network): - wallet = Wallet(storage) - self.update_wallet_format(wallet) - self.run_wallet_actions(wallet) - wallet.start_threads(network) - return wallet, None - - def create_new_wallet(self, storage, network): - action, wallet = self.create_or_restore(storage) - self.run_wallet_actions(wallet) - - if network: - self.choose_server(network) - else: - self.show_warning(_('You are offline')) - - def task(): - # Synchronize before starting the threads - wallet.synchronize() - wallet.start_threads(network) -# FIXME -# if action == 'create': -# msg = _('Wallet addresses generated.') -# else: -# wallet.wait_until_synchronized() -# if network: -# if wallet.is_found(): -# msg = _("Recovery successful") -# else: -# msg = _("No transactions found for this seed") -# else: -# msg = _("This wallet was restored offline. It may " -# "contain more addresses than displayed.") -# self.show_message(msg) - - return wallet, (MSG_GENERATING_WAIT, task) - + def show_restore(self, wallet, network, action): + """Show restore result""" + pass def open_wallet(self, network, filename): '''The main entry point of the wizard. Open a wallet from the given @@ -170,22 +136,43 @@ class WizardBase(PrintError): install wizard proper.''' storage = WalletStorage(filename) if storage.file_exists: - return self.open_existing_wallet(storage, network) + wallet = Wallet(storage) + self.update_wallet_format(wallet) + task = None else: - return self.create_new_wallet(storage, network) + cr, wallet = self.create_or_restore(storage) + if not wallet: + return + task = lambda: self.show_restore(wallet, network, cr) - def run_wallet_actions(self, wallet): - if not wallet: - return - action = orig_action = wallet.get_action() + action = wallet.get_action() + requires_action = action is not None while action: self.run_wallet_action(wallet, action) action = wallet.get_action() + # Save the wallet after successful completion of actions. # It will be saved again once synchronized. - if orig_action: + if requires_action: wallet.storage.write() + if network: + self.choose_server(network) + else: + self.show_warning(_('You are offline')) + + # start wallet threads + if network: + wallet.start_threads(network) + else: + wallet.synchronize() + + if task: + task() + + return wallet + + def run_wallet_action(self, wallet, action): self.print_error("action %s on %s" % (action, wallet.basename())) # Run the action on the wallet plugin, if any, then the