URI: 
       tupdate wallet format again, for keystore - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit afe39330dc2dda2c82294bff904a625cff7fb300
   DIR parent 428bc539b30d167e9eec77944a695b02319fc814
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sun, 21 Aug 2016 11:58:15 +0200
       
       update wallet format again, for keystore
       
       Diffstat:
         M lib/base_wizard.py                  |      16 +++++++---------
         M lib/keystore.py                     |     165 +++++++++++++------------------
         M lib/plugins.py                      |       8 ++++----
         M lib/storage.py                      |      67 ++++++++++++++++++++++++++-----
         M lib/wallet.py                       |      42 +++++++++++++------------------
         M plugins/trezor/plugin.py            |       5 +----
         M plugins/trezor/qt_generic.py        |      17 +++++++++++------
       
       7 files changed, 167 insertions(+), 153 deletions(-)
       ---
   DIR diff --git a/lib/base_wizard.py b/lib/base_wizard.py
       t@@ -148,7 +148,6 @@ class BaseWizard(object):
                self.restore_keys_dialog(title=title, message=message, run_next=self.on_restore, is_valid=v)
        
            def choose_hw(self):
       -        self.storage.put('key_type', 'hardware')
                hw_wallet_types, choices = self.plugins.hardware_wallets('create')
                choices = zip(hw_wallet_types, choices)
                title = _('Hardware Keystore')
       t@@ -162,7 +161,7 @@ class BaseWizard(object):
                self.choice_dialog(title=title, message=msg, choices=choices, run_next=self.on_hardware)
        
            def on_hardware(self, hw_type):
       -        self.storage.put('hardware_type', hw_type)
       +        self.hw_type = hw_type
                title = _('Hardware wallet') + ' [%s]' % hw_type
                message = _('Do you have a device, or do you want to restore a wallet using an existing seed?')
                choices = [
       t@@ -178,10 +177,9 @@ class BaseWizard(object):
            def on_hardware_account_id(self, account_id):
                from keystore import load_keystore, bip44_derivation
                derivation = bip44_derivation(int(account_id))
       -        self.storage.put('derivation', derivation)
       -        name = self.storage.get('hardware_type')
       -        plugin = self.plugins.get_plugin(name)
       -        plugin.on_create_wallet(self.storage, self)
       +        plugin = self.plugins.get_plugin(self.hw_type)
       +        k = plugin.create_keystore(self.hw_type, derivation, self)
       +        self.create_wallet(k, None)
        
            def on_hardware_seed(self):
                self.storage.put('key_type', 'hw_seed')
       t@@ -209,13 +207,13 @@ class BaseWizard(object):
                derivation = "m/44'/0'/%d'"%account_id
                self.storage.put('account_id', account_id)
                k.add_xprv_from_seed(bip32_seed, derivation, password)
       -        k.save(self.storage, 'x/')
       +        self.storage.put('keystore', k.dump())
                self.wallet = Standard_Wallet(self.storage)
                self.run('create_addresses')
        
            def create_wallet(self, k, password):
                if self.wallet_type == 'standard':
       -            k.save(self.storage, 'x/')
       +            self.storage.put('keystore', k.dump())
                    self.wallet = Standard_Wallet(self.storage)
                    self.run('create_addresses')
                elif self.wallet_type == 'multisig':
       t@@ -232,7 +230,7 @@ class BaseWizard(object):
                d = self.storage.get('master_public_keys', {})
                if keystore.xpub in d.values():
                    raise BaseException('duplicate key')
       -        keystore.save(self.storage, 'x%d/'%(i+1))
       +        self.storage.put('x%d/'%(i+1), keystore.dump())
        
            def add_cosigners(self, password, i):
                self.add_cosigner_dialog(run_next=lambda x: self.on_cosigner(x, password, i), index=i, is_valid=keystore.is_xpub)
   DIR diff --git a/lib/keystore.py b/lib/keystore.py
       t@@ -43,9 +43,6 @@ class KeyStore(PrintError):
            def has_seed(self):
                return False
        
       -    def has_password(self):
       -        return False
       -
            def is_watching_only(self):
                return False
        
       t@@ -57,10 +54,6 @@ class Software_KeyStore(KeyStore):
        
            def __init__(self):
                KeyStore.__init__(self)
       -        self.use_encryption = False
       -
       -    def has_password(self):
       -        return self.use_encryption
        
            def sign_message(self, sequence, message, password):
                sec = self.get_private_key(sequence, password)
       t@@ -79,9 +72,11 @@ class Software_KeyStore(KeyStore):
        class Imported_KeyStore(Software_KeyStore):
            # keystore for imported private keys
        
       -    def __init__(self):
       +    def __init__(self, d):
                Software_KeyStore.__init__(self)
       -        self.keypairs = {}
       +        self.keypairs = d.get('keypairs', {})
       +        self.receiving_pubkeys = self.keypairs.keys()
       +        self.change_pubkeys = []
        
            def is_deterministic(self):
                return False
       t@@ -92,16 +87,11 @@ class Imported_KeyStore(Software_KeyStore):
            def get_master_public_key(self):
                return None
        
       -    def load(self, storage, name):
       -        self.keypairs = storage.get('keypairs', {})
       -        self.use_encryption = storage.get('use_encryption', False)
       -        self.receiving_pubkeys = self.keypairs.keys()
       -        self.change_pubkeys = []
       -
       -    def save(self, storage, root_name):
       -        storage.put('key_type', 'imported')
       -        storage.put('keypairs', self.keypairs)
       -        storage.put('use_encryption', self.use_encryption)
       +    def dump(self):
       +        return {
       +            'type': 'imported',
       +            'keypairs': self.keypairs,
       +        }
        
            def can_import(self):
                return True
       t@@ -148,25 +138,21 @@ class Imported_KeyStore(Software_KeyStore):
                    b = pw_decode(v, old_password)
                    c = pw_encode(b, new_password)
                    self.keypairs[k] = b
       -        self.use_encryption = (new_password is not None)
        
        
        class Deterministic_KeyStore(Software_KeyStore):
        
       -    def __init__(self):
       +    def __init__(self, d):
                Software_KeyStore.__init__(self)
       -        self.seed = ''
       +        self.seed = d.get('seed', '')
        
            def is_deterministic(self):
                return True
        
       -    def load(self, storage, name):
       -        self.seed = storage.get('seed', '')
       -        self.use_encryption = storage.get('use_encryption', False)
       -
       -    def save(self, storage, name):
       -        storage.put('seed', self.seed)
       -        storage.put('use_encryption', self.use_encryption)
       +    def dump(self):
       +        return {
       +            'seed': self.seed,
       +        }
        
            def has_seed(self):
                return self.seed != ''
       t@@ -180,7 +166,6 @@ class Deterministic_KeyStore(Software_KeyStore):
                self.seed_version, self.seed = self.format_seed(seed)
                if password:
                    self.seed = pw_encode(self.seed, password)
       -        self.use_encryption = (password is not None)
        
            def get_seed(self, password):
                return pw_decode(self.seed, password).encode('utf8')
       t@@ -235,27 +220,21 @@ class Xpub:
        
        class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
        
       -    def __init__(self):
       +    def __init__(self, d):
                Xpub.__init__(self)
       -        Deterministic_KeyStore.__init__(self)
       -        self.xprv = None
       +        Deterministic_KeyStore.__init__(self, d)
       +        self.xpub = d.get('xpub')
       +        self.xprv = d.get('xprv')
        
            def format_seed(self, seed):
                return NEW_SEED_VERSION, ' '.join(seed.split())
        
       -    def load(self, storage, name):
       -        Deterministic_KeyStore.load(self, storage, name)
       -        self.xpub = storage.get('master_public_keys', {}).get(name)
       -        self.xprv = storage.get('master_private_keys', {}).get(name)
       -
       -    def save(self, storage, name):
       -        Deterministic_KeyStore.save(self, storage, name)
       -        d = storage.get('master_public_keys', {})
       -        d[name] = self.xpub
       -        storage.put('master_public_keys', d)
       -        d = storage.get('master_private_keys', {})
       -        d[name] = self.xprv
       -        storage.put('master_private_keys', d)
       +    def dump(self):
       +        d = Deterministic_KeyStore.dump(self)
       +        d['type'] = 'bip32'
       +        d['xpub'] = self.xpub
       +        d['xprv'] = self.xprv
       +        return d
        
            def add_master_private_key(self, xprv, password):
                self.xprv = pw_encode(xprv, password)
       t@@ -279,7 +258,6 @@ class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
                if self.xprv is not None:
                    b = pw_decode(self.xprv, old_password)
                    self.xprv = pw_encode(b, new_password)
       -        self.use_encryption = (new_password is not None)
        
            def is_watching_only(self):
                return self.xprv is None
       t@@ -340,18 +318,14 @@ class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
        
        class Old_KeyStore(Deterministic_KeyStore):
        
       -    def __init__(self):
       -        Deterministic_KeyStore.__init__(self)
       -        self.mpk = None
       -
       -    def load(self, storage, name):
       -        Deterministic_KeyStore.load(self, storage, name)
       -        self.mpk = storage.get('master_public_key').decode('hex')
       +    def __init__(self, d):
       +        Deterministic_KeyStore.__init__(self, d)
       +        self.mpk = d.get('mpk').decode('hex')
        
       -    def save(self, storage, name):
       -        Deterministic_KeyStore.save(self, storage, name)
       -        storage.put('wallet_type', 'old')
       -        storage.put('master_public_key', self.mpk.encode('hex'))
       +    def dump(self):
       +        d = Deterministic_KeyStore.dump(self)
       +        d['mpk'] = self.mpk.encode('hex')
       +        return d
        
            def add_seed(self, seed, password):
                Deterministic_KeyStore.add_seed(self, seed, password)
       t@@ -473,7 +447,6 @@ class Old_KeyStore(Deterministic_KeyStore):
                if self.has_seed():
                    decoded = self.get_seed(old_password)
                    self.seed = pw_encode(decoded, new_password)
       -        self.use_encryption = (new_password is not None)
        
        
        class Hardware_KeyStore(KeyStore, Xpub):
       t@@ -485,24 +458,26 @@ class Hardware_KeyStore(KeyStore, Xpub):
            #restore_wallet_class = BIP32_RD_Wallet
            max_change_outputs = 1
        
       -    def __init__(self):
       +    def __init__(self, d):
                Xpub.__init__(self)
                KeyStore.__init__(self)
                # Errors and other user interaction is done through the wallet's
                # handler.  The handler is per-window and preserved across
                # device reconnects
       +        self.xpub = d.get('xpub')
       +        self.derivation = d.get('derivation')
                self.handler = None
        
            def is_deterministic(self):
                return True
        
       -    def load(self, storage, name):
       -        self.xpub = storage.get('master_public_keys', {}).get(name)
       -
       -    def save(self, storage, name):
       -        d = storage.get('master_public_keys', {})
       -        d[name] = self.xpub
       -        storage.put('master_public_keys', d)
       +    def dump(self):
       +        return {
       +            'type': 'hardware',
       +            'hw_type': self.hw_type,
       +            'xpub': self.xpub,
       +            'derivation':self.derivation,
       +        }
        
            def unpaired(self):
                '''A device paired with the wallet was diconnected.  This can be
       t@@ -572,37 +547,37 @@ def xpubkey_to_address(x_pubkey):
            return pubkey, address
        
        
       -keystores = []
       +hw_keystores = {}
       +
       +def register_keystore(hw_type, constructor):
       +    hw_keystores[hw_type] = constructor
       +
       +def hardware_keystore(hw_type, d):
       +    if hw_type in hw_keystores:
       +        constructor = hw_keystores[hw_type]
       +        return constructor(d)
       +    raise BaseException('unknown hardware type', hw_type)
        
        def load_keystore(storage, name):
       -    w = storage.get('wallet_type')
       -    t = storage.get('key_type', 'seed')
       -    seed_version = storage.get_seed_version()
       -    if seed_version == OLD_SEED_VERSION or w == 'old':
       -        k = Old_KeyStore()
       +    w = storage.get('wallet_type', 'standard')
       +    d = storage.get(name, {})
       +    t = d.get('type')
       +    if not t:
       +        raise BaseException('wallet format requires update')
       +    if t == 'old':
       +        k = Old_KeyStore(d)
            elif t == 'imported':
       -        k = Imported_KeyStore()
       -    elif name and name not in [ 'x/', 'x1/' ]:
       -        k = BIP32_KeyStore()
       -    elif t in ['seed', 'hw_seed']:
       -        k = BIP32_KeyStore()
       +        k = Imported_KeyStore(d)
       +    elif t == 'bip32':
       +        k = BIP32_KeyStore(d)
            elif t == 'hardware':
       -        hw_type = storage.get('hardware_type')
       -        for cat, _type, constructor in keystores:
       -            if cat == 'hardware' and _type == hw_type:
       -                k = constructor()
       -                break
       -        else:
       -            raise BaseException('unknown hardware type')
       +        hw_type = d.get('hw_type')
       +        k = hardware_keystore(hw_type, d)
            else:
                raise BaseException('unknown wallet type', t)
       -    k.load(storage, name)
            return k
        
        
       -def register_keystore(category, type, constructor):
       -    keystores.append((category, type, constructor))
       -
        
        def is_old_mpk(mpk):
            try:
       t@@ -649,35 +624,35 @@ def bip44_derivation(account_id):
        
        def from_seed(seed, password):
            if is_old_seed(seed):
       -        keystore = Old_KeyStore()
       +        keystore = Old_KeyStore({})
                keystore.add_seed(seed, password)
            elif is_new_seed(seed):
       -        keystore = BIP32_KeyStore()
       +        keystore = BIP32_KeyStore({})
                keystore.add_seed(seed, password)
                bip32_seed = Mnemonic.mnemonic_to_seed(seed, '')
                keystore.add_xprv_from_seed(bip32_seed, "m/", password)
            return keystore
        
        def from_private_key_list(text, password):
       -    keystore = Imported_KeyStore()
       +    keystore = Imported_KeyStore({})
            for x in text.split():
                keystore.import_key(x, None)
            keystore.update_password(None, password)
            return keystore
        
        def from_old_mpk(mpk):
       -    keystore = Old_KeyStore()
       +    keystore = Old_KeyStore({})
            keystore.add_master_public_key(mpk)
            return keystore
        
        def from_xpub(xpub):
       -    keystore = BIP32_KeyStore()
       +    keystore = BIP32_KeyStore({})
            keystore.add_master_public_key(xpub)
            return keystore
        
        def from_xprv(xprv, password):
            xpub = bitcoin.xpub_from_xprv(xprv)
       -    keystore = BIP32_KeyStore()
       +    keystore = BIP32_KeyStore({})
            keystore.add_master_private_key(xprv, password)
            keystore.add_master_public_key(xpub)
            return keystore
   DIR diff --git a/lib/plugins.py b/lib/plugins.py
       t@@ -164,12 +164,12 @@ class Plugins(DaemonThread):
        
            def register_keystore(self, name, gui_good, details):
                from keystore import register_keystore
       -        def dynamic_constructor():
       -            return self.get_plugin(name).keystore_class()
       +        def dynamic_constructor(d):
       +            return self.get_plugin(name).keystore_class(d)
                if details[0] == 'hardware':
                    self.hw_wallets[name] = (gui_good, details)
       -            self.print_error("registering keystore %s: %s" %(name, details))
       -        register_keystore(details[0], details[1], dynamic_constructor)
       +            self.print_error("registering hardware %s: %s" %(name, details))
       +            register_keystore(details[1], dynamic_constructor)
        
            def get_plugin(self, name):
                if not name in self.plugins:
   DIR diff --git a/lib/storage.py b/lib/storage.py
       t@@ -37,6 +37,17 @@ from i18n import _
        from util import NotEnoughFunds, PrintError, profiler
        from plugins import run_hook, plugin_loaders
        from keystore import bip44_derivation
       +from version import OLD_SEED_VERSION
       +
       +
       +def multisig_type(wallet_type):
       +    '''If wallet_type is mofn multi-sig, return [m, n],
       +    otherwise return None.'''
       +    match = re.match('(\d+)of(\d+)', wallet_type)
       +    if match:
       +        match = [int(x) for x in match.group(1, 2)]
       +    return match
       +
        
        class WalletStorage(PrintError):
        
       t@@ -198,8 +209,9 @@ class WalletStorage(PrintError):
        
            def requires_upgrade(self):
                r = False
       -        r |= self.convert_wallet_type(True)
       -        r |= self.convert_imported(True)
       +        if self.file_exists:
       +            r |= self.convert_wallet_type(True)
       +            r |= self.convert_imported(True)
                return r
        
            def upgrade(self):
       t@@ -209,17 +221,52 @@ class WalletStorage(PrintError):
        
            def convert_wallet_type(self, is_test):
                assert not self.requires_split()
       -        wallet_type = self.get('wallet_type')
       -        if wallet_type not in ['trezor', 'keepkey']:
       +        d = self.get('keystore', {})
       +        t = d.get('type')
       +        if t:
                    return False
                if is_test:
                    return True
       -        self.put('wallet_type', 'standard')
       -        self.put('key_type', 'hardware')
       -        self.put('hardware_type', wallet_type)
       -        xpub = self.get('master_public_keys')["x/0'"]
       -        self.put('master_public_keys', {'x/': xpub})
       -        self.put('derivation', bip44_derivation(0))
       +        wallet_type = self.get('wallet_type')
       +        seed_version = self.get_seed_version()
       +        if seed_version == OLD_SEED_VERSION or wallet_type == 'old':
       +            seed = self.get('seed')
       +            d = {
       +                'type': 'old',
       +                'seed': seed
       +            }
       +            self.put('wallet_type', 'standard')
       +            self.put('keystore', d)
       +
       +        elif wallet_type == 'standard':
       +            xpub = self.get('master_public_keys')["x/"]
       +            xprv = self.get('master_private_keys')["x/"]
       +            d = {
       +                'type': 'bip32',
       +                'xpub': xpub,
       +                'xprv': xprv,
       +                'seed': self.get('seed', '')
       +            }
       +            self.put('wallet_type', 'standard')
       +            self.put('keystore', d)
       +
       +        elif wallet_type in ['trezor', 'keepkey']:
       +            xpub = self.get('master_public_keys')["x/0'"]
       +            d = {
       +                'type': 'hardware',
       +                'hardware_type': wallet_type,
       +                'xpub': xpub,
       +                'derivation': bip44_derivation(0),
       +            }
       +            self.put('wallet_type', 'standard')
       +            self.put('keystore', d)
       +
       +        elif multisig_type(wallet_type):
       +            raise BaseException('not implemented')
       +
       +        elif wallet_type in ['2fa']:
       +            raise BaseException('not implemented')
       +
        
            def convert_imported(self, test):
                # '/x' is the internal ID for imported accounts
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -50,6 +50,7 @@ from util import NotEnoughFunds, PrintError, profiler
        from bitcoin import *
        from version import *
        from keystore import load_keystore
       +from storage import multisig_type
        
        from transaction import Transaction
        from plugins import run_hook
       t@@ -1164,6 +1165,9 @@ class Abstract_Wallet(PrintError):
                if self.synchronizer:
                    self.synchronizer.add(address)
        
       +    def has_password(self):
       +        return self.storage.get('use_encryption', False)
       +
        
        class Imported_Wallet(Abstract_Wallet):
            # wallet made of imported addresses
       t@@ -1242,7 +1246,7 @@ class P2PK_Wallet(Abstract_Wallet):
                return public_key_to_bc_address(pubkey.decode('hex'))
        
            def load_keystore(self):
       -        self.keystore = load_keystore(self.storage, self.root_name)
       +        self.keystore = load_keystore(self.storage, 'keystore')
        
            def get_pubkey(self, c, i):
                pubkey_list = self.change_pubkeys if c else self.receiving_pubkeys
       t@@ -1402,7 +1406,6 @@ class Deterministic_Wallet(Abstract_Wallet):
        
        
        class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
       -    root_name = 'x/'
            wallet_type = 'standard'
        
            def __init__(self, storage):
       t@@ -1426,22 +1429,23 @@ class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
            def can_change_password(self):
                return self.keystore.can_change_password()
        
       -    def has_password(self):
       -        return self.keystore.has_password()
       -
            def check_password(self, password):
                self.keystore.check_password(password)
        
            def update_password(self, old_pw, new_pw):
                self.keystore.update_password(old_pw, new_pw)
       -        self.keystore.save(self.storage, self.root_name)
       +        self.save_keystore()
       +        self.storage.put('use_encryption', (new_pw is not None))
       +
       +    def save_keystore(self):
       +        self.storage.put('keystore', self.keystore.dump())
        
            def can_import_privkey(self):
                return self.keystore.can_import()
        
            def import_key(self, pk, pw):
                pubkey = self.keystore.import_key(pk, pw)
       -        self.keystore.save(self.storage, self.root_name)
       +        self.save_keystore()
                self.receiving_pubkeys.append(pubkey)
                self.save_pubkeys()
                addr = self.pubkeys_to_address(pubkey)
       t@@ -1452,12 +1456,11 @@ class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
        
        class Multisig_Wallet(Deterministic_Wallet):
            # generic m of n
       -    root_name = "x1/"
            gap_limit = 20
        
            def __init__(self, storage):
                self.wallet_type = storage.get('wallet_type')
       -        self.m, self.n = Wallet.multisig_type(self.wallet_type)
       +        self.m, self.n = multisig_type(self.wallet_type)
                Deterministic_Wallet.__init__(self, storage)
        
            def get_pubkeys(self, c, i):
       t@@ -1481,10 +1484,10 @@ class Multisig_Wallet(Deterministic_Wallet):
                for i in range(self.n):
                    name = 'x%d/'%(i+1)
                    self.keystores[name] = load_keystore(self.storage, name)
       -        self.keystore = self.keystores[self.root_name]
       +        self.keystore = self.keystores['x1/']
        
            def get_keystore(self):
       -        return self.keystores.get(self.root_name)
       +        return self.keystores.get('x1/')
        
            def get_keystores(self):
                return self.keystores.values()
       t@@ -1492,7 +1495,8 @@ class Multisig_Wallet(Deterministic_Wallet):
            def update_password(self, old_pw, new_pw):
                for name, keystore in self.keystores.items():
                    keystore.update_password(old_pw, new_pw)
       -            keystore.save(self.storage, name)
       +            self.storage.put(name, keystore.dump())
       +        self.storage.put('use_encryption', (new_pw is not None))
        
            def has_seed(self):
                return self.keystore.has_seed()
       t@@ -1500,9 +1504,6 @@ class Multisig_Wallet(Deterministic_Wallet):
            def can_change_password(self):
                return self.keystore.can_change_password()
        
       -    def has_password(self):
       -        return self.keystore.has_password()
       -
            def is_watching_only(self):
                return not any([not k.is_watching_only() for k in self.get_keystores()])
        
       t@@ -1568,18 +1569,9 @@ class Wallet(object):
        
            @staticmethod
            def wallet_class(wallet_type):
       -        if Wallet.multisig_type(wallet_type):
       +        if multisig_type(wallet_type):
                    return Multisig_Wallet
                if wallet_type in wallet_constructors:
                    return wallet_constructors[wallet_type]
                raise RuntimeError("Unknown wallet type: " + wallet_type)
        
       -    @staticmethod
       -    def multisig_type(wallet_type):
       -        '''If wallet_type is mofn multi-sig, return [m, n],
       -        otherwise return None.'''
       -        match = re.match('(\d+)of(\d+)', wallet_type)
       -        if match:
       -            match = [int(x) for x in match.group(1, 2)]
       -        return match
       -
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -20,10 +20,7 @@ from ..hw_wallet import HW_PluginBase
        TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, TIM_PRIVKEY = range(0, 4)
        
        class TrezorCompatibleKeyStore(Hardware_KeyStore):
       -
       -    def load(self, storage, name):
       -        self.xpub = storage.get('master_public_keys', {}).get(name)
       -        self.derivation = storage.get('derivation')
       +    hw_type = 'trezor'
        
            def get_derivation(self):
                return self.derivation
   DIR diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py
       t@@ -284,14 +284,13 @@ def qt_plugin_class(base_plugin_class):
                # Trigger a pairing
                keystore.thread.add(partial(self.get_client, keystore))
        
       -    def on_create_wallet(self, storage, wizard):
       -        from electrum.keystore import load_keystore
       +    def create_keystore(self, hw_type, derivation, wizard):
       +        from electrum.keystore import hardware_keystore
                handler = self.create_handler(wizard)
                thread = TaskThread(wizard, wizard.on_error)
                # Setup device and create accounts in separate thread; wait until done
                loop = QEventLoop()
                exc_info = []
       -        derivation = storage.get('derivation')
                self.setup_device(derivation, thread, handler, on_done=loop.quit,
                                  on_error=lambda info: exc_info.extend(info))
                loop.exec_()
       t@@ -299,9 +298,15 @@ def qt_plugin_class(base_plugin_class):
                if exc_info:
                    wizard.on_error(exc_info)
                    raise UserCancelled
       -        storage.put('master_public_keys', {'/x':self.xpub})
       -        keystore = load_keystore(storage, '/x') # this calls the dynamic constructor
       -        wizard.create_wallet(keystore, None)
       +        # create keystore
       +        d = {
       +            'xpub': self.xpub,
       +            'type': 'hardware',
       +            'hw_type': hw_type,
       +            'derivation': derivation
       +        }
       +        k = hardware_keystore(hw_type, d)
       +        return k
        
            @hook
            def receive_menu(self, menu, addrs, wallet):