tdetect if wallet can sign tx before showing sign button - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 2c7bf3ca1aff2326f3cc788f57c9c4289d0366f5 DIR parent b32d0c77a3afcfbfa3b551610cab3cba4ddd84c9 HTML Author: ThomasV <thomasv@gitorious> Date: Tue, 24 Jun 2014 13:22:10 +0200 detect if wallet can sign tx before showing sign button Diffstat: M gui/qt/transaction_dialog.py | 9 ++++----- M lib/account.py | 2 ++ M lib/transaction.py | 30 ++++++++++++++++++++++++++++++ M lib/wallet.py | 65 +++++++++++++++++-------------- 4 files changed, 72 insertions(+), 34 deletions(-) --- DIR diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py t@@ -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(): t@@ -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' DIR diff --git a/lib/account.py b/lib/account.py t@@ -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): DIR diff --git a/lib/transaction.py b/lib/transaction.py t@@ -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) DIR diff --git a/lib/wallet.py b/lib/wallet.py t@@ -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