URI: 
       tseparate signtxwithkey and signtxwithwallet, and simplify sign_transaction - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 581ed1ed26f9a215b090840d83f7791832c25aa3
   DIR parent c1226b0f6ea3679f25a71a060fc03413d9dcbd64
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Thu, 30 Oct 2014 16:36:29 +0100
       
       separate signtxwithkey and signtxwithwallet, and simplify sign_transaction
       
       Diffstat:
         M electrum                            |       3 ---
         M gui/qt/main_window.py               |       6 ++----
         M lib/commands.py                     |      13 ++++++++++---
         M lib/transaction.py                  |      10 ++++++----
         M lib/wallet.py                       |      80 ++++++++++++++-----------------
       
       5 files changed, 53 insertions(+), 59 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -375,9 +375,6 @@ if __name__ == '__main__':
                if len(args) == 1:
                    args.append(prompt_password('Enter PrivateKey (will not echo):', False))
        
       -    elif cmd.name == 'signrawtransaction':
       -        args = [cmd, args[1], json.loads(args[2]) if len(args) > 2 else [] ]
       -
            elif cmd.name == 'createmultisig':
                args = [cmd, int(args[1]), json.loads(args[2])]
        
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -1113,9 +1113,7 @@ class ElectrumWindow(QMainWindow):
                def sign_thread():
                    if self.wallet.is_watching_only():
                        return tx
       -            keypairs = {}
       -            self.wallet.add_keypairs(tx, keypairs, password)
       -            self.wallet.sign_transaction(tx, keypairs, password)
       +            self.wallet.sign_transaction(tx, password)
                    return tx
        
                def sign_done(tx):
       t@@ -2179,7 +2177,7 @@ class ElectrumWindow(QMainWindow):
            @protected
            def sign_raw_transaction(self, tx, password):
                try:
       -            self.wallet.signrawtransaction(tx, [], password)
       +            self.wallet.sign_transaction(tx, password)
                except Exception as e:
                    traceback.print_exc(file=sys.stdout)
                    QMessageBox.warning(self, _("Error"), str(e))
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -97,7 +97,8 @@ register_command('restore',              0, 0, True,  True,  False, 'Restore a w
        register_command('setconfig',            2, 2, False, False, False, 'Set a configuration variable', 'setconfig <name> <value>')
        register_command('setlabel',             2,-1, False, True,  False, 'Assign a label to an item', 'setlabel <tx_hash> <label>')
        register_command('sendrawtransaction',   1, 1, True,  False, False, 'Broadcasts a transaction to the network.', 'sendrawtransaction <tx in hexadecimal>')
       -register_command('signrawtransaction',   1, 3, False, True,  True,  'Sign a serailized transaction','signrawtransaction <tx in hexadecimal>')
       +register_command('signtxwithkey',        1, 3, False, False, False, 'Sign a serialized transaction with a key','signtxwithkey <tx> <key>')
       +register_command('signtxwithwallet',     1, 3, False, True,  True,  'Sign a serialized transaction with a wallet','signtxwithwallet <tx>')
        register_command('signmessage',          2,-1, False, True,  True,  'Sign a message with a key', signmessage_syntax)
        register_command('unfreeze',             1, 1, False, True,  False, 'Unfreeze the funds at one of your wallet\'s address', 'unfreeze <address>')
        register_command('validateaddress',      1, 1, False, False, False, 'Check that the address is valid', 'validateaddress <address>')
       t@@ -164,9 +165,15 @@ class Commands:
                tx = Transaction(inputs, outputs)
                return tx
        
       -    def signrawtransaction(self, raw_tx, private_keys):
       +    def signtxwithkey(self, raw_tx, sec):
                tx = Transaction.deserialize(raw_tx)
       -        self.wallet.signrawtransaction(tx, private_keys, self.password)
       +        pubkey = bitcoin.public_key_from_private_key(sec)
       +        tx.sign({ pubkey:sec })
       +        return tx
       +
       +    def signtxwithwallet(self, raw_tx):
       +        tx = Transaction.deserialize(raw_tx)
       +        self.wallet.sign_transaction(tx, self.password)
                return tx
        
            def decoderawtransaction(self, raw):
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -322,7 +322,9 @@ def x_to_xpub(x_pubkey):
        
        
        def parse_xpub(x_pubkey):
       -    if x_pubkey[0:2] == 'ff':
       +    if x_pubkey[0:2] in ['02','03','04']:
       +        pubkey = x_pubkey
       +    elif x_pubkey[0:2] == 'ff':
                from account import BIP32_Account
                xpub, s = BIP32_Account.parse_xpubkey(x_pubkey)
                pubkey = BIP32_Account.derive_pubkey_from_xpub(xpub, s[0], s[1])
       t@@ -331,7 +333,7 @@ def parse_xpub(x_pubkey):
                mpk, s = OldAccount.parse_xpubkey(x_pubkey)
                pubkey = OldAccount.get_pubkey_from_mpk(mpk.decode('hex'), s[0], s[1])
            else:
       -        pubkey = x_pubkey
       +        raise BaseException("Cannnot parse pubkey")
            return pubkey
        
        
       t@@ -595,8 +597,8 @@ class Transaction:
            def serialize(self, for_sig=None):
                # for_sig:
                #   -1   : do not sign, estimate length
       -        #   i>=0 : sign input i
       -        #   None : add all signatures
       +        #   i>=0 : serialized tx for signing input i
       +        #   None : add all known signatures
        
                inputs = self.inputs
                outputs = self.outputs
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -362,45 +362,6 @@ class Abstract_Wallet(object):
                account_id, sequence = self.get_address_index(address)
                return self.accounts[account_id].get_pubkeys(*sequence)
        
       -    def add_keypairs(self, tx, keypairs, password):
       -
       -        if self.is_watching_only():
       -            return
       -        self.check_password(password)
       -
       -        addr_list, xpub_list = tx.inputs_to_sign()
       -        for addr in addr_list:
       -            if self.is_mine(addr):
       -                private_keys = self.get_private_key(addr, 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
       -            pk = account.get_private_key(sequence, self, password)
       -            for sec in pk:
       -                pubkey = public_key_from_private_key(sec)
       -                keypairs[pubkey] = sec
       -
       -    def signrawtransaction(self, tx, private_keys, password):
       -        # check that the password is correct. This will raise if it's not.
       -        self.check_password(password)
       -        # build a list of public/private keys
       -        keypairs = {}
       -        # add private keys from parameter
       -        for sec in private_keys:
       -            pubkey = public_key_from_private_key(sec)
       -            keypairs[ pubkey ] = sec
       -        # add private_keys
       -        self.add_keypairs(tx, keypairs, password)
       -        # sign the transaction
       -        self.sign_transaction(tx, keypairs, password)
        
            def sign_message(self, address, message, password):
                keys = self.get_private_key(address, password)
       t@@ -777,10 +738,7 @@ class Abstract_Wallet(object):
        
            def mktx(self, outputs, password, fee=None, change_addr=None, domain= None, coins = None ):
                tx = self.make_unsigned_transaction(outputs, fee, change_addr, domain, coins)
       -        keypairs = {}
       -        self.add_keypairs(tx, keypairs, password)
       -        if keypairs:
       -            self.sign_transaction(tx, keypairs, password)
       +        self.sign_transaction(tx, password)
                return tx
        
            def add_input_info(self, txin):
       t@@ -803,8 +761,40 @@ class Abstract_Wallet(object):
                    txin['redeemPubkey'] = account.get_pubkey(*sequence)
                    txin['num_sig'] = 1
        
       -    def sign_transaction(self, tx, keypairs, password):
       -        tx.sign(keypairs)
       +    def sign_transaction(self, tx, password):
       +        if self.is_watching_only():
       +            return
       +        # check that the password is correct. This will raise if it's not.
       +        self.check_password(password)
       +
       +
       +        keypairs = {}
       +
       +        # tx.inputs_to_sign() : return list of addresses or derivations
       +        # this list should be enriched by add_keypairs
       +        addr_list, xpub_list = tx.inputs_to_sign()
       +        for addr in addr_list:
       +            if self.is_mine(addr):
       +                private_keys = self.get_private_key(addr, 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
       +            pk = account.get_private_key(sequence, self, password)
       +            for sec in pk:
       +                pubkey = public_key_from_private_key(sec)
       +                keypairs[pubkey] = sec
       +
       +        if keypairs:
       +            tx.sign(keypairs)
       +
                run_hook('sign_transaction', tx, password)
        
            def sendtx(self, tx):