URI: 
       tBIP32_HD_Wallet: Fix address derivation - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 3d781a2d1b93d33b7232ba95b8f11e583e8ad436
   DIR parent 4743f033b4f1761bb8971b01ca94cee72b671531
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Sun, 10 Jan 2016 19:53:28 +0900
       
       BIP32_HD_Wallet: Fix address derivation
       
       Unfortunately there was root_name and root_derivation confusion
       in the past for classes derived from BIP_32_HD_Wallet.
       Address derivation used root_name and so would begin with 'x/'
       whereas it should have begun with root_derivation, and so started
       with 'm/'.
       
       This fixes that old wart and removes some fudges from the trezor
       code that used to work around it.
       
       Diffstat:
         M lib/wallet.py                       |      20 +++++++-------------
         M plugins/ledger/ledger.py            |       4 ++++
         M plugins/trezor/client.py            |       2 +-
         M plugins/trezor/plugin.py            |       1 -
       
       4 files changed, 12 insertions(+), 15 deletions(-)
       ---
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -1668,19 +1668,15 @@ class BIP32_HD_Wallet(BIP32_Wallet):
                # drop unused master public key to avoid duplicate errors
                acc2 = storage.get('next_account2', None)
                if acc2:
       -            storage.put('next_account2', None)
                    self.master_public_keys.pop(self.root_name + acc2[0] + "'", None)
       -            self.storage.put('master_public_keys', self.master_public_keys)
       +            storage.put('next_account2', None)
       +            storage.put('master_public_keys', self.master_public_keys)
        
            def next_account_number(self):
                assert (set(self.accounts.keys()) ==
                        set(['%d' % n for n in range(len(self.accounts))]))
                return len(self.accounts)
        
       -    def next_derivation(self):
       -        account_id = '%d' % self.next_account_number()
       -        return self.root_name + account_id + "'", account_id
       -
            def show_account(self, account_id):
                return self.account_is_used(account_id) or account_id in self.labels
        
       t@@ -1711,8 +1707,10 @@ class BIP32_HD_Wallet(BIP32_Wallet):
                self.create_next_account(password)
        
            def create_next_account(self, password, label=None):
       -        derivation, account_id = self.next_derivation()
       -        xpub, xprv = self.derive_xkeys(self.root_name, derivation, password)
       +        account_id = '%d' % self.next_account_number()
       +        derivation = self.account_derivation(account_id)
       +        root_name = self.root_derivation.split('/')[0]  # NOT self.root_name!
       +        xpub, xprv = self.derive_xkeys(root_name, derivation, password)
                self.add_master_public_key(derivation, xpub)
                if xprv:
                    self.add_master_private_key(derivation, xprv, password)
       t@@ -1729,12 +1727,8 @@ class BIP32_HD_Wallet(BIP32_Wallet):
                return all(self.account_is_used(acc_id) for acc_id in self.accounts)
        
            @classmethod
       -    def prefix(self):
       -        return "/".join(self.root_derivation.split("/")[1:])
       -
       -    @classmethod
            def account_derivation(self, account_id):
       -        return self.prefix() + "/" + account_id + "'"
       +        return self.root_derivation + "/" + account_id + "'"
        
            @classmethod
            def address_derivation(self, account_id, change, address_index):
   DIR diff --git a/plugins/ledger/ledger.py b/plugins/ledger/ledger.py
       t@@ -63,6 +63,10 @@ class BTChipWallet(BIP44_Wallet):
                assert not self.has_seed()
                return self.force_watching_only
        
       +    def address_id(self, address):
       +        # Strip the leading "m/"
       +        return BIP44_Wallet.address_id(self, address)[2:]
       +
            def get_client(self, noPin=False):
                if not BTCHIP:
                    self.give_error('please install github.com/btchip/btchip-python')
   DIR diff --git a/plugins/trezor/client.py b/plugins/trezor/client.py
       t@@ -98,7 +98,7 @@ def trezor_client_class(protocol_mixin, base_client, proto):
                    '''Convert bip32 path to list of uint32 integers with prime flags
                    0/-1/1' -> [0, 0x80000001, 0x80000001]'''
                    path = []
       -            for x in n.split('/'):
       +            for x in n.split('/')[1:]:
                        prime = 0
                        if x.endswith("'"):
                            x = x.replace('\'', '')
   DIR diff --git a/plugins/trezor/plugin.py b/plugins/trezor/plugin.py
       t@@ -100,7 +100,6 @@ class TrezorCompatibleWallet(BIP44_Wallet):
        
                # When creating a wallet we need to ask the device for the
                # master public key
       -        derivation = derivation.replace(self.root_name, self.prefix() + "/")
                xpub = self.get_public_key(derivation)
                return xpub, None