restore from xprv

This commit is contained in:
ThomasV 2014-06-25 16:45:55 +02:00
parent ace101e4f5
commit 54973062bd
3 changed files with 88 additions and 38 deletions

View File

@ -176,11 +176,11 @@ class InstallWizard(QDialog):
def is_any(self, seed_e): def is_any(self, seed_e):
text = self.get_seed_text(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): def is_mpk(self, seed_e):
text = self.get_seed_text(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): def enter_seed_dialog(self, msg, sid):
@ -211,7 +211,7 @@ class InstallWizard(QDialog):
hbox, button = ok_cancel_buttons2(self, _('Next')) hbox, button = ok_cancel_buttons2(self, _('Next'))
vbox.addLayout(hbox) vbox.addLayout(hbox)
button.setEnabled(False) 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: for e in entries:
e.textChanged.connect(f) e.textChanged.connect(f)
self.set_layout(vbox) self.set_layout(vbox)
@ -476,8 +476,13 @@ class InstallWizard(QDialog):
wallet = Wallet.from_seed(text, self.storage) wallet = Wallet.from_seed(text, self.storage)
wallet.add_seed(text, password) wallet.add_seed(text, password)
wallet.create_accounts(password) wallet.create_accounts(password)
elif Wallet.is_mpk(text): elif Wallet.is_xprv(text):
wallet = Wallet.from_mpk(text, self.storage) 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): elif Wallet.is_address(text):
wallet = Wallet.from_address(text, self.storage) wallet = Wallet.from_address(text, self.storage)
elif Wallet.is_private_key(text): elif Wallet.is_private_key(text):

View File

@ -656,6 +656,27 @@ def deserialize_xkey(xkey):
return depth, fingerprint, child_number, c, K_or_k 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): def bip32_root(seed):
import hmac import hmac

View File

@ -1266,8 +1266,11 @@ class NewWallet(Deterministic_Wallet):
def __init__(self, storage): def __init__(self, storage):
Deterministic_Wallet.__init__(self, storage) Deterministic_Wallet.__init__(self, storage)
def is_watching_only(self):
return self.master_private_keys is {}
def can_create_accounts(self): 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): def get_master_public_key(self):
return self.master_public_keys["m/"] return self.master_public_keys["m/"]
@ -1291,19 +1294,29 @@ class NewWallet(Deterministic_Wallet):
xpub = self.master_public_keys["m/"] xpub = self.master_public_keys["m/"]
assert deserialize_xkey(xpriv)[3] == deserialize_xkey(xpub)[3] assert deserialize_xkey(xpriv)[3] == deserialize_xkey(xpub)[3]
def create_watching_only_wallet(self, xpub): def create_xprv_wallet(self, xprv, password):
self.storage.put('seed_version', self.seed_version, True) xpub = bitcoin.xpub_from_xprv(xprv)
self.add_master_public_key("m/", xpub)
account = BIP32_Account({'xpub':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_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})
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): def create_accounts(self, password):
# First check the password is valid (this raises if it isn't). # First check the password is valid (this raises if it isn't).
self.check_password(password) self.check_password(password)
self.create_account('Main account', password) self.create_account('Main account', password)
def add_master_public_key(self, name, mpk): def add_master_public_key(self, name, xpub):
self.master_public_keys[name] = mpk self.master_public_keys[name] = xpub
self.storage.put('master_public_keys', self.master_public_keys, True) self.storage.put('master_public_keys', self.master_public_keys, True)
def add_master_private_key(self, name, xpriv, password): def add_master_private_key(self, name, xpriv, password):
@ -1576,18 +1589,28 @@ class Wallet(object):
return False return False
@classmethod @classmethod
def is_mpk(self, mpk): def is_old_mpk(self, mpk):
try: try:
int(mpk, 16) int(mpk, 16)
old = True assert len(mpk) == 128
return True
except: except:
old = False return False
if old: @classmethod
return len(mpk) == 128 def is_xpub(self, text):
else:
try: try:
deserialize_xkey(mpk) 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 return True
except: except:
return False return False
@ -1635,19 +1658,20 @@ class Wallet(object):
return w return w
@classmethod @classmethod
def from_mpk(self, mpk, storage): def from_old_mpk(self, mpk, storage):
try:
int(mpk, 16)
old = True
except:
old = False
if old:
w = OldWallet(storage) w = OldWallet(storage)
w.seed = '' w.seed = ''
w.create_watching_only_wallet(mpk) w.create_watching_only_wallet(mpk)
else: return w
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 return w