Browse Source

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.
master
Neil Booth 10 years ago
parent
commit
3d781a2d1b
  1. 20
      lib/wallet.py
  2. 4
      plugins/ledger/ledger.py
  3. 2
      plugins/trezor/client.py
  4. 1
      plugins/trezor/plugin.py

20
lib/wallet.py

@ -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
@ -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)
@ -1728,13 +1726,9 @@ class BIP32_HD_Wallet(BIP32_Wallet):
def accounts_all_used(self):
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):

4
plugins/ledger/ledger.py

@ -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')

2
plugins/trezor/client.py

@ -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('\'', '')

1
plugins/trezor/plugin.py

@ -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

Loading…
Cancel
Save