detect if wallet can sign tx before showing sign button
authorThomasV <thomasv@gitorious>
Tue, 24 Jun 2014 11:22:10 +0000 (13:22 +0200)
committerThomasV <thomasv@gitorious>
Tue, 24 Jun 2014 11:22:10 +0000 (13:22 +0200)
gui/qt/transaction_dialog.py
lib/account.py
lib/transaction.py
lib/wallet.py

index 55ce205..a2f3f96 100644 (file)
@@ -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'
 
index a99fc2e..9925660 100644 (file)
@@ -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):
index 968d5dd..973e642 100644 (file)
@@ -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)
 
index 6b241c6..69226da 100644 (file)
@@ -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