commit 2c7bf3ca1aff2326f3cc788f57c9c4289d0366f5
parent b32d0c77a3afcfbfa3b551610cab3cba4ddd84c9
Author: ThomasV <thomasv@gitorious>
Date: Tue, 24 Jun 2014 13:22:10 +0200
detect if wallet can sign tx before showing sign button
Diffstat:
4 files changed, 72 insertions(+), 34 deletions(-)
diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py
@@ -131,10 +131,13 @@ class TxDialog(QDialog):
def update(self):
is_relevant, is_mine, v, fee = self.wallet.get_tx_value(self.tx)
+ if self.wallet.can_sign(self.tx):
+ self.sign_button.show()
+ else:
+ self.sign_button.hide()
if self.tx.is_complete():
status = _("Signed")
- self.sign_button.hide()
tx_hash = self.tx.hash()
if tx_hash in self.wallet.transactions.keys():
@@ -153,10 +156,6 @@ class TxDialog(QDialog):
s, r = self.tx.signature_count()
status = _("Unsigned") if s == 0 else _('Partially signed (%d/%d)'%(s,r))
time_str = None
- if not self.wallet.is_watching_only():
- self.sign_button.show()
- else:
- self.sign_button.hide()
self.broadcast_button.hide()
tx_hash = 'unknown'
diff --git a/lib/account.py b/lib/account.py
@@ -75,6 +75,8 @@ class PendingAccount(Account):
def get_name(self, k):
return _('Pending account')
+ def get_master_pubkeys(self):
+ return []
class ImportedAccount(Account):
def __init__(self, d):
diff --git a/lib/transaction.py b/lib/transaction.py
@@ -618,6 +618,36 @@ class Transaction:
return r == s
+ def inputs_to_sign(self):
+ from account import BIP32_Account, OldAccount
+ xpub_list = []
+ addr_list = set()
+ for txin in self.inputs:
+ x_signatures = txin['signatures']
+ signatures = filter(lambda x: x is not None, x_signatures)
+
+ if len(signatures) == txin['num_sig']:
+ # input is complete
+ continue
+
+ for k, x_pubkey in enumerate(txin['x_pubkeys']):
+
+ if x_signatures[k] is not None:
+ # this pubkey already signed
+ continue
+
+ if x_pubkey[0:2] == 'ff':
+ xpub, sequence = BIP32_Account.parse_xpubkey(x_pubkey)
+ xpub_list.append((xpub,sequence))
+ elif x_pubkey[0:2] == 'fe':
+ xpub, sequence = OldAccount.parse_xpubkey(x_pubkey)
+ xpub_list.add((xpub,sequence))
+ else:
+ addr_list.add(txin['address'])
+
+ return addr_list, xpub_list
+
+
def sign(self, keypairs):
print_error("tx.sign(), keypairs:", keypairs)
diff --git a/lib/wallet.py b/lib/wallet.py
@@ -392,47 +392,54 @@ class Abstract_Wallet:
return self.accounts[account_id].get_pubkeys(sequence)
+ def can_sign(self, tx):
+
+ if self.is_watching_only():
+ return False
+
+ if tx.is_complete():
+ return False
+
+ addr_list, xpub_list = tx.inputs_to_sign()
+ for addr in addr_list:
+ if self.is_mine(addr):
+ return True
+
+ mpk = [ self.master_public_keys[k] for k in self.master_private_keys.keys() ]
+ for xpub, sequence in xpub_list:
+ if xpub in mpk:
+ return True
+
+ return False
+
+
+
def add_keypairs(self, tx, keypairs, password):
# first check the provided password
seed = self.get_seed(password)
- for txin in tx.inputs:
- x_pubkeys = txin['x_pubkeys']
- address = txin['address']
-
- if self.is_mine(address):
+ addr_list, xpub_list = tx.inputs_to_sign()
+ for addr in addr_list:
+ if self.is_mine(addr):
private_keys = self.get_private_key(address, password)
for sec in private_keys:
pubkey = public_key_from_private_key(sec)
keypairs[ pubkey ] = sec
+ for xpub, sequence in xpub_list:
+ # look for account that can sign
+ for k, account in self.accounts.items():
+ if xpub in account.get_master_pubkeys():
+ break
else:
+ continue
- from account import BIP32_Account, OldAccount
- for x_pubkey in x_pubkeys:
- if not is_extended_pubkey(x_pubkey):
- continue
-
- if x_pubkey[0:2] == 'ff':
- xpub, sequence = BIP32_Account.parse_xpubkey(x_pubkey)
- elif x_pubkey[0:2] == 'fe':
- xpub, sequence = OldAccount.parse_xpubkey(x_pubkey)
-
- # look for account that can sign
- for k, account in self.accounts.items():
- if xpub in account.get_master_pubkeys():
- break
- else:
- continue
-
- addr = account.get_address(*sequence)
- assert txin['address'] == addr
- pk = self.get_private_key(addr, password)
- for sec in pk:
- pubkey = public_key_from_private_key(sec)
- keypairs[pubkey] = sec
-
+ addr = account.get_address(*sequence)
+ pk = self.get_private_key(addr, password)
+ for sec in pk:
+ pubkey = public_key_from_private_key(sec)
+ keypairs[pubkey] = sec