URI: 
       tfix: import addresses and private keys - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f6e393d7b602029aad82fc138abd5e5f32390d91
   DIR parent 5733a5d125266fd596922cdf7c1019c520c28272
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 17 Aug 2016 10:39:30 +0200
       
       fix: import addresses and private keys
       
       Diffstat:
         M gui/qt/address_list.py              |       2 +-
         M gui/qt/main_window.py               |      55 +++++++++++++++++--------------
         M lib/base_wizard.py                  |       2 +-
         M lib/wallet.py                       |      36 +++++++++++++++++--------------
       
       4 files changed, 53 insertions(+), 42 deletions(-)
       ---
   DIR diff --git a/gui/qt/address_list.py b/gui/qt/address_list.py
       t@@ -132,7 +132,7 @@ class AddressList(MyTreeWidget):
                        menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr))
                        menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr))
                    if is_imported:
       -                menu.addAction(_("Remove from wallet"), lambda: self.parent.delete_imported_key(addr))
       +                menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr))
                    addr_URL = block_explorer_URL(self.config, 'addr', addr)
                    if addr_URL:
                        menu.addAction(_("View on block explorer"), lambda: webbrowser.open(addr_URL))
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -297,7 +297,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                    title += ' [%s]' % (_('watching only'))
                self.setWindowTitle(title)
                self.password_menu.setEnabled(self.wallet.can_change_password())
       -        self.import_menu.setVisible(self.wallet.can_import())
       +        self.import_privkey_menu.setVisible(self.wallet.can_import_privkey())
       +        self.import_address_menu.setVisible(self.wallet.can_import_address())
                self.export_menu.setEnabled(self.wallet.can_export())
        
            def warn_if_watching_only(self):
       t@@ -395,8 +396,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
                self.private_keys_menu = wallet_menu.addMenu(_("&Private keys"))
                self.private_keys_menu.addAction(_("&Sweep"), self.sweep_key_dialog)
       -        self.import_menu = self.private_keys_menu.addAction(_("&Import"), self.do_import_privkey)
       +        self.import_privkey_menu = self.private_keys_menu.addAction(_("&Import"), self.do_import_privkey)
                self.export_menu = self.private_keys_menu.addAction(_("&Export"), self.export_privkeys_dialog)
       +        self.import_address_menu = wallet_menu.addAction(_("Import addresses"), self.import_addresses)
                wallet_menu.addAction(_("&Export History"), self.export_history_dialog)
                wallet_menu.addAction(_("Search"), self.toggle_search).setShortcut(QKeySequence("Ctrl+S"))
                wallet_menu.addAction(_("Addresses"), self.toggle_addresses_tab).setShortcut(QKeySequence("Ctrl+A"))
       t@@ -1408,9 +1410,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.contact_list = l = ContactList(self)
                return self.create_list_tab(l)
        
       -    def delete_imported_key(self, addr):
       +    def remove_address(self, addr):
                if self.question(_("Do you want to remove")+" %s "%addr +_("from your wallet?")):
       -            self.wallet.delete_imported_key(addr)
       +            self.wallet.delete_address(addr)
                    self.address_list.update()
                    self.history_list.update()
        
       t@@ -2196,34 +2198,39 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                self.warn_if_watching_only()
                self.show_transaction(tx)
        
       -
       -    @protected
       -    def do_import_privkey(self, password):
       -        if not self.wallet.keystore.can_import():
       -            return
       -        text = text_dialog(self, _('Import private keys'), _("Enter private keys")+':', _("Import"))
       +    def _do_import(self, title, msg, func):
       +        text = text_dialog(self, title, msg + ' :', _('Import'))
                if not text:
                    return
       -        text = str(text).split()
       -        badkeys = []
       -        addrlist = []
       -        for key in text:
       +        bad = []
       +        good = []
       +        for key in str(text).split():
                    try:
       -                addr = self.wallet.import_key(key, password)
       +                addr = func(key)
       +                good.append(addr)
                    except BaseException as e:
       -                badkeys.append(key)
       +                bad.append(key)
                        continue
       -            if not addr:
       -                badkeys.append(key)
       -            else:
       -                addrlist.append(addr)
       -        if addrlist:
       -            self.show_message(_("The following addresses were added") + ':\n' + '\n'.join(addrlist))
       -        if badkeys:
       -            self.show_critical(_("The following inputs could not be imported") + ':\n'+ '\n'.join(badkeys))
       +        if good:
       +            self.show_message(_("The following addresses were added") + ':\n' + '\n'.join(good))
       +        if bad:
       +            self.show_critical(_("The following inputs could not be imported") + ':\n'+ '\n'.join(bad))
                self.address_list.update()
                self.history_list.update()
        
       +    def import_addresses(self):
       +        if not self.wallet.can_import_address():
       +            return
       +        title, msg = _('Import addresses'), _("Enter addresses")
       +        self._do_import(title, msg, self.wallet.import_address)
       +
       +    @protected
       +    def do_import_privkey(self, password):
       +        if not self.wallet.can_import_privkey():
       +            return
       +        title, msg = _('Import private keys'), _("Enter private keys")
       +        self._do_import(title, msg, lambda x: self.wallet.import_key(x, password))
       +
        
            def settings_dialog(self):
                self.need_restart = False
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -124,7 +124,7 @@ class BaseWizard(object):
                if keystore.is_address_list(text):
                    self.wallet = Imported_Wallet(self.storage)
                    for x in text.split():
       -                self.wallet.add_address(x)
       +                self.wallet.import_address(x)
                    self.terminate()
                elif keystore.is_private(text):
                    self.add_password(text)
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1152,9 +1152,17 @@ class Abstract_Wallet(PrintError):
            def get_fingerprint(self):
                raise NotImplementedError()
        
       -    def can_import(self):
       +    def can_import_privkey(self):
                return False
        
       +    def can_import_address(self):
       +        return False
       +
       +    def add_address(self, address):
       +        if address not in self.history:
       +            self.history[address] = []
       +        if self.synchronizer:
       +            self.synchronizer.add(address)
        
        
        class Imported_Wallet(Abstract_Wallet):
       t@@ -1177,7 +1185,7 @@ class Imported_Wallet(Abstract_Wallet):
            def can_change_password(self):
                return False
        
       -    def can_import(self):
       +    def can_import_address(self):
                return True
        
            def is_watching_only(self):
       t@@ -1204,20 +1212,22 @@ class Imported_Wallet(Abstract_Wallet):
            def get_addresses(self, include_change=False):
                return self.addresses
        
       -    def add_address(self, address):
       +    def import_address(self, address):
                if address in self.addresses:
                    return
                self.addresses.append(address)
                self.storage.put('addresses', self.addresses)
                self.storage.write()
       -
       -        # force resynchronization, because we need to re-run add_transaction
       -        if address in self.history:
       -            self.history.pop(address)
       -        if self.synchronizer:
       -            self.synchronizer.add(address)
       +        self.add_address(address)
                return address
        
       +    def delete_address(self, address):
       +        if address not in self.addresses:
       +            return
       +        self.addresses.remove(address)
       +        self.storage.put('addresses', self.addresses)
       +        self.storage.write()
       +
            def get_receiving_addresses(self):
                return self.addresses[:]
        
       t@@ -1332,12 +1342,6 @@ class Deterministic_Wallet(Abstract_Wallet):
                        if n > nmax: nmax = n
                return nmax + 1
        
       -    def add_address(self, address):
       -        if address not in self.history:
       -            self.history[address] = []
       -        if self.synchronizer:
       -            self.synchronizer.add(address)
       -
            def create_new_address(self, for_change):
                pubkey_list = self.change_pubkeys if for_change else self.receiving_pubkeys
                n = len(pubkey_list)
       t@@ -1432,7 +1436,7 @@ class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
                self.keystore.update_password(old_pw, new_pw)
                self.keystore.save(self.storage, self.root_name)
        
       -    def can_import(self):
       +    def can_import_privkey(self):
                return self.keystore.can_import()
        
            def import_key(self, pk, pw):