commit f0611c456938eb485da765895dc482456fa292d1
parent f4d5efbf3b09d9798fbdd05a6d57ec8b8a1ab076
Author: ThomasV <thomasv@electrum.org>
Date: Wed, 12 Oct 2016 12:03:56 +0200
fix pubkey indexing in imported wallets
Diffstat:
3 files changed, 55 insertions(+), 32 deletions(-)
diff --git a/gui/qt/address_list.py b/gui/qt/address_list.py
@@ -95,9 +95,9 @@ class AddressList(MyTreeWidget):
address_item.addChild(utxo_item)
def create_menu(self, position):
- from electrum.wallet import Multisig_Wallet, Imported_Wallet
+ from electrum.wallet import Multisig_Wallet
is_multisig = isinstance(self.wallet, Multisig_Wallet)
- is_imported = isinstance(self.wallet, Imported_Wallet)
+ can_delete = self.wallet.can_delete_address()
selected = self.selectedItems()
multi_select = len(selected) > 1
addrs = [unicode(item.text(0)) for item in selected]
@@ -131,7 +131,7 @@ class AddressList(MyTreeWidget):
if not is_multisig and not self.wallet.is_watching_only():
menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr))
menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr))
- if is_imported:
+ if can_delete:
menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr))
addr_URL = block_explorer_URL(self.config, 'addr', addr)
if addr_URL:
diff --git a/lib/keystore.py b/lib/keystore.py
@@ -116,8 +116,6 @@ class Imported_KeyStore(Software_KeyStore):
def __init__(self, d):
Software_KeyStore.__init__(self)
self.keypairs = d.get('keypairs', {})
- self.receiving_pubkeys = self.keypairs.keys()
- self.change_pubkeys = []
def is_deterministic(self):
return False
@@ -138,7 +136,8 @@ class Imported_KeyStore(Software_KeyStore):
return True
def check_password(self, password):
- self.get_private_key((0,0), password)
+ pubkey = self.keypairs.keys()[0]
+ self.get_private_key(pubkey, password)
def import_key(self, sec, password):
try:
@@ -147,24 +146,12 @@ class Imported_KeyStore(Software_KeyStore):
raise BaseException('Invalid private key')
# allow overwrite
self.keypairs[pubkey] = pw_encode(sec, password)
- self.receiving_pubkeys = self.keypairs.keys()
return pubkey
def delete_imported_key(self, key):
self.keypairs.pop(key)
- def get_public_key(self, sequence):
- for_change, i = sequence
- pubkey = (self.change_pubkeys if for_change else self.receiving_pubkeys)[i]
- return pubkey
-
- def get_xpubkey(self, c, i):
- return self.get_public_key((c,i))
-
- def get_private_key(self, sequence, password):
- for_change, i = sequence
- assert for_change == 0
- pubkey = self.receiving_pubkeys[i]
+ def get_private_key(self, pubkey, password):
pk = pw_decode(self.keypairs[pubkey], password)
# this checks the password
if pubkey != public_key_from_private_key(pk):
@@ -173,15 +160,14 @@ class Imported_KeyStore(Software_KeyStore):
def get_pubkey_derivation(self, x_pubkey):
if x_pubkey[0:2] in ['02', '03', '04']:
- if x_pubkey in self.receiving_pubkeys:
- i = self.receiving_pubkeys.index(x_pubkey)
- return (False, i)
+ if x_pubkey in self.keypairs.keys():
+ return x_pubkey
elif x_pubkey[0:2] == 'fd':
# fixme: this assumes p2pkh
_, addr = xpubkey_to_address(x_pubkey)
- for i, pubkey in enumerate(self.receiving_pubkeys):
+ for pubkey in self.keypairs.keys():
if public_key_to_bc_address(pubkey.decode('hex')) == addr:
- return (False, i)
+ return pubkey
def update_password(self, old_password, new_password):
self.check_password(old_password)
diff --git a/lib/wallet.py b/lib/wallet.py
@@ -269,8 +269,23 @@ class Abstract_Wallet(PrintError):
def get_private_key(self, address, password):
if self.is_watching_only():
return []
- sequence = self.get_address_index(address)
- return [ self.keystore.get_private_key(sequence, password) ]
+ if self.keystore.can_import():
+ i = self.receiving_addresses.index(address)
+ pubkey = self.receiving_pubkeys[i]
+ pk = self.keystore.get_private_key(pubkey, password)
+ else:
+ sequence = self.get_address_index(address)
+ pk = self.keystore.get_private_key(sequence, password)
+ return [pk]
+
+ def get_public_key(self, address):
+ if self.keystore.can_import():
+ i = self.receiving_addresses.index(address)
+ pubkey = self.receiving_pubkeys[i]
+ else:
+ sequence = self.get_address_index(address)
+ pubkey = self.get_pubkey(*sequence)
+ return pubkey
def get_public_keys(self, address):
sequence = self.get_address_index(address)
@@ -1170,7 +1185,6 @@ class Abstract_Wallet(PrintError):
self.receive_requests[key] = req
self.storage.put('payment_requests', self.receive_requests)
-
def add_payment_request(self, req, config):
import os
addr = req['address']
@@ -1231,6 +1245,9 @@ class Abstract_Wallet(PrintError):
def can_import_address(self):
return False
+ def can_delete_address(self):
+ return False
+
def add_address(self, address):
if address not in self.history:
self.history[address] = []
@@ -1302,6 +1319,9 @@ class Imported_Wallet(Abstract_Wallet):
self.add_address(address)
return address
+ def can_delete_address(self):
+ return True
+
def delete_address(self, address):
if address not in self.addresses:
return
@@ -1336,8 +1356,7 @@ class P2PK_Wallet(Abstract_Wallet):
return pubkey_list[i]
def get_public_keys(self, address):
- sequence = self.get_address_index(address)
- return [self.get_pubkey(*sequence)]
+ return [self.get_public_key(address)]
def get_pubkey_index(self, pubkey):
if pubkey in self.receiving_pubkeys:
@@ -1347,9 +1366,15 @@ class P2PK_Wallet(Abstract_Wallet):
raise BaseExeption('pubkey not found')
def add_input_sig_info(self, txin, address):
- txin['derivation'] = derivation = self.get_address_index(address)
- x_pubkey = self.keystore.get_xpubkey(*derivation)
- pubkey = self.get_pubkey(*derivation)
+ if not self.keystore.can_import():
+ txin['derivation'] = derivation = self.get_address_index(address)
+ x_pubkey = self.keystore.get_xpubkey(*derivation)
+ pubkey = self.get_pubkey(*derivation)
+ else:
+ pubkey = self.get_public_key(address)
+ assert pubkey is not None
+ x_pubkey = pubkey
+
txin['x_pubkeys'] = [x_pubkey]
txin['pubkeys'] = [pubkey]
txin['signatures'] = [None]
@@ -1527,6 +1552,17 @@ class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
def save_keystore(self):
self.storage.put('keystore', self.keystore.dump())
+ def can_delete_address(self):
+ return self.keystore.can_import()
+
+ def delete_address(self, address):
+ pubkey = self.get_public_key(address)
+ self.keystore.delete_imported_key(pubkey)
+ self.save_keystore()
+ self.receiving_pubkeys.remove(pubkey)
+ self.receiving_addresses.remove(addr)
+ self.storage.write()
+
def can_import_privkey(self):
return self.keystore.can_import()
@@ -1537,6 +1573,7 @@ class Standard_Wallet(Deterministic_Wallet, P2PK_Wallet):
self.save_pubkeys()
addr = self.pubkeys_to_address(pubkey)
self.receiving_addresses.append(addr)
+ self.storage.write()
self.add_address(addr)
return addr