URI: 
       tupdate ledger plugin - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 9c7fd44b58b4eb18711e9206654f92c8b21d0aae
   DIR parent eb60e0d2e092e2bddce2734a0bb2efdb6fd5437e
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sun, 21 Aug 2016 22:44:42 +0200
       
       update ledger plugin
       
       Diffstat:
         M plugins/ledger/__init__.py          |       2 +-
         M plugins/ledger/ledger.py            |     110 +++++++++++++++----------------
         M plugins/ledger/qt.py                |      21 +++++++++++++++------
       
       3 files changed, 69 insertions(+), 64 deletions(-)
       ---
   DIR diff --git a/plugins/ledger/__init__.py b/plugins/ledger/__init__.py
       t@@ -3,5 +3,5 @@ from electrum.i18n import _
        fullname = 'Ledger Wallet'
        description = 'Provides support for Ledger hardware wallet'
        requires = [('btchip', 'github.com/ledgerhq/btchip-python')]
       -registers_keystore = ('hardware', 'btchip', _("Ledger wallet"))
       +registers_keystore = ('hardware', 'ledger', _("Ledger wallet"))
        available_for = ['qt', 'cmdline']
   DIR diff --git a/plugins/ledger/ledger.py b/plugins/ledger/ledger.py
       t@@ -27,26 +27,19 @@ except ImportError:
        
        
        class Ledger_KeyStore(Hardware_KeyStore):
       -    wallet_type = 'btchip'
            device = 'Ledger'
        
       -    def __init__(self):
       -        Hardware_KeyStore.__init__(self)
       +    def __init__(self, d):
       +        Hardware_KeyStore.__init__(self, d)
                # Errors and other user interaction is done through the wallet's
                # handler.  The handler is per-window and preserved across
                # device reconnects
       -        self.handler = None
                self.force_watching_only = False
                self.device_checked = False
                self.signing = False
       -        self.client = None
        
       -    def get_derivation(self):
       -        return "m/44'/0'/%d'"%self.account_id
       -
       -    def load(self, storage, name):
       -        self.xpub = storage.get('master_public_keys', {}).get(name)
       -        self.account_id = int(storage.get('account_id'))
       +    def get_client(self):
       +        return self.plugin.get_client()
        
            def init_xpub(self):
                client = self.get_client()
       t@@ -67,42 +60,6 @@ class Ledger_KeyStore(Hardware_KeyStore):
                # Strip the leading "m/"
                return BIP32_HW_Wallet.address_id(self, address)[2:]
        
       -    def get_public_key(self, bip32_path):
       -        # bip32_path is of the form 44'/0'/1'
       -        # S-L-O-W - we don't handle the fingerprint directly, so compute
       -        # it manually from the previous node
       -        # This only happens once so it's bearable
       -        self.get_client() # prompt for the PIN before displaying the dialog if necessary
       -        self.handler.show_message("Computing master public key")
       -        try:
       -            splitPath = bip32_path.split('/')
       -            if splitPath[0] == 'm':
       -                splitPath = splitPath[1:]
       -                bip32_path = bip32_path[2:]
       -            fingerprint = 0
       -            if len(splitPath) > 1:
       -                prevPath = "/".join(splitPath[0:len(splitPath) - 1])
       -                nodeData = self.get_client().getWalletPublicKey(prevPath)
       -                publicKey = compress_public_key(nodeData['publicKey'])
       -                h = hashlib.new('ripemd160')
       -                h.update(hashlib.sha256(publicKey).digest())
       -                fingerprint = unpack(">I", h.digest()[0:4])[0]
       -            nodeData = self.get_client().getWalletPublicKey(bip32_path)
       -            publicKey = compress_public_key(nodeData['publicKey'])
       -            depth = len(splitPath)
       -            lastChild = splitPath[len(splitPath) - 1].split('\'')
       -            if len(lastChild) == 1:
       -                childnum = int(lastChild[0])
       -            else:
       -                childnum = 0x80000000 | int(lastChild[0])
       -            xpub = "0488B21E".decode('hex') + chr(depth) + self.i4b(fingerprint) + self.i4b(childnum) + str(nodeData['chainCode']) + str(publicKey)
       -        except Exception, e:
       -            self.give_error(e, True)
       -        finally:
       -            self.handler.clear_dialog()
       -
       -        return EncodeBase58Check(xpub)
       -
            def decrypt_message(self, pubkey, message, password):
                self.give_error("Not supported")
        
       t@@ -318,6 +275,21 @@ class Ledger_KeyStore(Hardware_KeyStore):
                    return False, None, None
                return True, response, response
        
       +
       +class LedgerPlugin(HW_PluginBase):
       +    libraries_available = BTCHIP
       +    keystore_class = Ledger_KeyStore
       +    hw_type='ledger'
       +    client = None
       +
       +    def btchip_is_connected(self, keystore):
       +        try:
       +            self.get_client().getFirmwareVersion()
       +        except Exception as e:
       +            self.print_error("get_client", str(e))
       +            return False
       +        return True
       +
            def get_client(self, force_pair=True, noPin=False):
                aborted = False
                client = self.client
       t@@ -389,15 +361,39 @@ class Ledger_KeyStore(Hardware_KeyStore):
        
                return self.client
        
       +    def get_public_key(self, bip32_path):
       +        # bip32_path is of the form 44'/0'/1'
       +        # S-L-O-W - we don't handle the fingerprint directly, so compute
       +        # it manually from the previous node
       +        # This only happens once so it's bearable
       +        self.get_client() # prompt for the PIN before displaying the dialog if necessary
       +        self.handler.show_message("Computing master public key")
       +        try:
       +            splitPath = bip32_path.split('/')
       +            if splitPath[0] == 'm':
       +                splitPath = splitPath[1:]
       +                bip32_path = bip32_path[2:]
       +            fingerprint = 0
       +            if len(splitPath) > 1:
       +                prevPath = "/".join(splitPath[0:len(splitPath) - 1])
       +                nodeData = self.get_client().getWalletPublicKey(prevPath)
       +                publicKey = compress_public_key(nodeData['publicKey'])
       +                h = hashlib.new('ripemd160')
       +                h.update(hashlib.sha256(publicKey).digest())
       +                fingerprint = unpack(">I", h.digest()[0:4])[0]
       +            nodeData = self.get_client().getWalletPublicKey(bip32_path)
       +            publicKey = compress_public_key(nodeData['publicKey'])
       +            depth = len(splitPath)
       +            lastChild = splitPath[len(splitPath) - 1].split('\'')
       +            if len(lastChild) == 1:
       +                childnum = int(lastChild[0])
       +            else:
       +                childnum = 0x80000000 | int(lastChild[0])
       +            xpub = "0488B21E".decode('hex') + chr(depth) + self.i4b(fingerprint) + self.i4b(childnum) + str(nodeData['chainCode']) + str(publicKey)
       +        except Exception, e:
       +            self.give_error(e, True)
       +        finally:
       +            self.handler.clear_dialog()
        
       -class LedgerPlugin(HW_PluginBase):
       -    libraries_available = BTCHIP
       -    keystore_class = Ledger_KeyStore
       +        return EncodeBase58Check(xpub)
        
       -    def btchip_is_connected(self, keystore):
       -        try:
       -            keystore.get_client().getFirmwareVersion()
       -        except Exception as e:
       -            self.print_error("get_client", str(e))
       -            return False
       -        return True
   DIR diff --git a/plugins/ledger/qt.py b/plugins/ledger/qt.py
       t@@ -25,12 +25,21 @@ class Plugin(LedgerPlugin):
                    window.show_error(_("Ledger device not detected.\nContinuing in watching-only mode."))
                    wallet.force_watching_only = True
        
       -    def on_create_wallet(self, keystore, wizard):
       -        assert type(keystore) == self.keystore_class
       -        keystore.handler = BTChipQTHandler(wizard)
       -        keystore.init_xpub()
       -        print keystore.xpub
       -        wizard.create_wallet(keystore, None)
       +    def create_keystore(self, hw_type, derivation, wizard):
       +        from electrum.keystore import hardware_keystore
       +        # create keystore
       +        handler = BTChipQTHandler(wizard)
       +        client = self.get_client()
       +        xpub = self.get_public_key(derivation)
       +        d = {
       +            'xpub': self.xpub,
       +            'type': 'hardware',
       +            'hw_type': hw_type,
       +            'derivation': derivation
       +        }
       +        k = hardware_keystore(hw_type, d)
       +        return k
       +
        
        class BTChipQTHandler(QtHandlerBase):