commit 6b45070b2f7c899dd9bdd1a7bf423ad23a014374
parent 2d48aa35af94bfc26ac3353ae732b71b8ee6d93c
Author: ThomasV <thomasv@electrum.org>
Date: Tue, 20 Jun 2017 10:47:02 +0200
allow arbitrary derivations with bip39 seeds, to let multibit users recover funds
Diffstat:
3 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
@@ -453,7 +453,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
line = QLineEdit()
line.setText(default)
def f(text):
- self.next_button.setEnabled(test(text))
+ self.next_button.setEnabled(test(unicode(text)))
line.textEdited.connect(f)
vbox.addWidget(line)
vbox.addWidget(WWLabel(warning))
diff --git a/lib/base_wizard.py b/lib/base_wizard.py
@@ -222,21 +222,16 @@ class BaseWizard(object):
# This is partially compatible with BIP45; assumes index=0
self.on_hw_derivation(name, device_info, "m/45'/0")
else:
- f = lambda x: self.run('on_hw_derivation', name, device_info, bip44_derivation(int(x)))
- self.account_id_dialog(f)
+ f = lambda x: self.run('on_hw_derivation', name, device_info, str(x))
+ self.derivation_dialog(f)
- def account_id_dialog(self, f):
+ def derivation_dialog(self, f):
+ default = bip44_derivation(0)
message = '\n'.join([
- _('Enter your BIP44 account number here.'),
- _('If you are not sure what this is, leave this field to zero.')
+ _('Enter your wallet derivation here.'),
+ _('If you are not sure what this is, leave this field unchanged.')
])
- def is_int(x):
- try:
- int(x)
- return True
- except:
- return False
- self.line_dialog(run_next=f, title=_('Account Number'), message=message, default='0', test=is_int)
+ self.line_dialog(run_next=f, title=_('Derivation'), message=message, default=default, test=bitcoin.is_bip32_derivation)
def on_hw_derivation(self, name, device_info, derivation):
from keystore import hardware_keystore
@@ -293,17 +288,16 @@ class BaseWizard(object):
raise BaseException('Unknown seed type', seed_type)
def on_restore_bip39(self, seed, passphrase):
- f = lambda x: self.run('on_bip44', seed, passphrase, int(x))
- self.account_id_dialog(f)
+ f = lambda x: self.run('on_bip44', seed, passphrase, str(x))
+ self.derivation_dialog(f)
def create_keystore(self, seed, passphrase):
k = keystore.from_seed(seed, passphrase)
self.on_keystore(k)
- def on_bip44(self, seed, passphrase, account_id):
+ def on_bip44(self, seed, passphrase, derivation):
k = keystore.BIP32_KeyStore({})
bip32_seed = keystore.bip39_to_seed(seed, passphrase)
- derivation = bip44_derivation(account_id)
k.add_xprv_from_seed(bip32_seed, 0, derivation)
self.on_keystore(k)
diff --git a/lib/bitcoin.py b/lib/bitcoin.py
@@ -820,6 +820,21 @@ def xpub_from_pubkey(xtype, cK):
return serialize_xpub(xtype, chr(0)*32, cK)
+def bip32_derivation(s):
+ assert s.startswith('m/')
+ s = s[2:]
+ for n in s.split('/'):
+ if n == '': continue
+ i = int(n[:-1]) + BIP32_PRIME if n[-1] == "'" else int(n)
+ yield i
+
+def is_bip32_derivation(x):
+ try:
+ [ i for i in bip32_derivation(x)]
+ return True
+ except :
+ return False
+
def bip32_private_derivation(xprv, branch, sequence):
assert sequence.startswith(branch)
if branch == sequence: