commit 54973062bd903bda787bb94a66bc4eff7b35b77b
parent ace101e4f5d1ff98a722640cf4a0329e2480136c
Author: ThomasV <thomasv@gitorious>
Date: Wed, 25 Jun 2014 16:45:55 +0200
restore from xprv
Diffstat:
3 files changed, 85 insertions(+), 35 deletions(-)
diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
@@ -176,11 +176,11 @@ class InstallWizard(QDialog):
def is_any(self, seed_e):
text = self.get_seed_text(seed_e)
- return Wallet.is_seed(text) or Wallet.is_mpk(text) or Wallet.is_address(text) or Wallet.is_private_key(text)
+ return Wallet.is_seed(text) or Wallet.is_old_mpk(text) or Wallet.is_xpub(text) or Wallet.is_xprv(text) or Wallet.is_address(text) or Wallet.is_private_key(text)
def is_mpk(self, seed_e):
text = self.get_seed_text(seed_e)
- return Wallet.is_mpk(text)
+ return Wallet.is_xpub(text) or Wallet.is_old_mpk(text)
def enter_seed_dialog(self, msg, sid):
@@ -211,7 +211,7 @@ class InstallWizard(QDialog):
hbox, button = ok_cancel_buttons2(self, _('Next'))
vbox.addLayout(hbox)
button.setEnabled(False)
- f = lambda: button.setEnabled( map(lambda e: self.is_mpk(e), entries) == [True]*len(entries))
+ f = lambda: button.setEnabled( map(lambda e: self.is_xpub(e), entries) == [True]*len(entries))
for e in entries:
e.textChanged.connect(f)
self.set_layout(vbox)
@@ -476,8 +476,13 @@ class InstallWizard(QDialog):
wallet = Wallet.from_seed(text, self.storage)
wallet.add_seed(text, password)
wallet.create_accounts(password)
- elif Wallet.is_mpk(text):
- wallet = Wallet.from_mpk(text, self.storage)
+ elif Wallet.is_xprv(text):
+ password = self.password_dialog()
+ wallet = Wallet.from_xprv(text, password, self.storage)
+ elif Wallet.is_old_mpk(text):
+ wallet = Wallet.from_old_mpk(text, self.storage)
+ elif Wallet.is_xpub(text):
+ wallet = Wallet.from_xpub(text, self.storage)
elif Wallet.is_address(text):
wallet = Wallet.from_address(text, self.storage)
elif Wallet.is_private_key(text):
diff --git a/lib/bitcoin.py b/lib/bitcoin.py
@@ -656,6 +656,27 @@ def deserialize_xkey(xkey):
return depth, fingerprint, child_number, c, K_or_k
+def get_xkey_name(xkey):
+ depth, fingerprint, child_number, c, K = deserialize_xkey(xkey)
+ n = int(child_number.encode('hex'), 16)
+ if n & BIP32_PRIME:
+ child_id = "%d'"%(n - BIP32_PRIME)
+ else:
+ child_id = "%d"%n
+ if depth == 0:
+ return ''
+ elif depth == 1:
+ return child_id
+ else:
+ raise BaseException("xpub depth error")
+
+
+def xpub_from_xprv(xprv):
+ depth, fingerprint, child_number, c, k = deserialize_xkey(xprv)
+ K, cK = get_pubkeys_from_secret(k)
+ xpub = "0488B21E".decode('hex') + chr(depth) + fingerprint + child_number + c + cK
+ return EncodeBase58Check(xpub)
+
def bip32_root(seed):
import hmac
diff --git a/lib/wallet.py b/lib/wallet.py
@@ -1266,8 +1266,11 @@ class NewWallet(Deterministic_Wallet):
def __init__(self, storage):
Deterministic_Wallet.__init__(self, storage)
+ def is_watching_only(self):
+ return self.master_private_keys is {}
+
def can_create_accounts(self):
- return not self.is_watching_only()
+ return 'm/' in self.master_private_keys.keys()
def get_master_public_key(self):
return self.master_public_keys["m/"]
@@ -1291,19 +1294,29 @@ class NewWallet(Deterministic_Wallet):
xpub = self.master_public_keys["m/"]
assert deserialize_xkey(xpriv)[3] == deserialize_xkey(xpub)[3]
- def create_watching_only_wallet(self, xpub):
+ def create_xprv_wallet(self, xprv, password):
+ xpub = bitcoin.xpub_from_xprv(xprv)
+ account = BIP32_Account({'xpub':xpub})
+ account_id = 'm/' + bitcoin.get_xkey_name(xpub)
self.storage.put('seed_version', self.seed_version, True)
- self.add_master_public_key("m/", xpub)
+ self.add_master_private_key(account_id, xprv, password)
+ self.add_master_public_key(account_id, xpub)
+ self.add_account(account_id, account)
+
+ def create_watching_only_wallet(self, xpub):
account = BIP32_Account({'xpub':xpub})
- self.add_account("m/", account)
+ account_id = 'm/' + bitcoin.get_xkey_name(xpub)
+ self.storage.put('seed_version', self.seed_version, True)
+ self.add_master_public_key(account_id, xpub)
+ self.add_account(account_id, account)
def create_accounts(self, password):
# First check the password is valid (this raises if it isn't).
self.check_password(password)
self.create_account('Main account', password)
- def add_master_public_key(self, name, mpk):
- self.master_public_keys[name] = mpk
+ def add_master_public_key(self, name, xpub):
+ self.master_public_keys[name] = xpub
self.storage.put('master_public_keys', self.master_public_keys, True)
def add_master_private_key(self, name, xpriv, password):
@@ -1576,21 +1589,31 @@ class Wallet(object):
return False
@classmethod
- def is_mpk(self, mpk):
+ def is_old_mpk(self, mpk):
try:
int(mpk, 16)
- old = True
+ assert len(mpk) == 128
+ return True
except:
- old = False
+ return False
- if old:
- return len(mpk) == 128
- else:
- try:
- deserialize_xkey(mpk)
- return True
- except:
- return False
+ @classmethod
+ def is_xpub(self, text):
+ try:
+ assert text[0:4] == 'xpub'
+ deserialize_xkey(text)
+ return True
+ except:
+ return False
+
+ @classmethod
+ def is_xprv(self, text):
+ try:
+ assert text[0:4] == 'xprv'
+ deserialize_xkey(text)
+ return True
+ except:
+ return False
@classmethod
def is_address(self, text):
@@ -1635,19 +1658,20 @@ class Wallet(object):
return w
@classmethod
- def from_mpk(self, mpk, storage):
- try:
- int(mpk, 16)
- old = True
- except:
- old = False
+ def from_old_mpk(self, mpk, storage):
+ w = OldWallet(storage)
+ w.seed = ''
+ w.create_watching_only_wallet(mpk)
+ return w
- if old:
- w = OldWallet(storage)
- w.seed = ''
- w.create_watching_only_wallet(mpk)
- else:
- w = NewWallet(storage)
- w.create_watching_only_wallet(mpk)
+ @classmethod
+ def from_xpub(self, xpub, storage):
+ w = NewWallet(storage)
+ w.create_watching_only_wallet(xpub)
+ return w
+ @classmethod
+ def from_xprv(self, xprv, password, storage):
+ w = NewWallet(storage)
+ w.create_xprv_wallet(xprv, password)
return w