electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 581ed1ed26f9a215b090840d83f7791832c25aa3
parent c1226b0f6ea3679f25a71a060fc03413d9dcbd64
Author: ThomasV <thomasv@gitorious>
Date:   Thu, 30 Oct 2014 16:36:29 +0100

separate signtxwithkey and signtxwithwallet, and simplify sign_transaction

Diffstat:
Melectrum | 3---
Mgui/qt/main_window.py | 6++----
Mlib/commands.py | 13++++++++++---
Mlib/transaction.py | 10++++++----
Mlib/wallet.py | 80+++++++++++++++++++++++++++++++++++--------------------------------------------
5 files changed, 53 insertions(+), 59 deletions(-)

diff --git a/electrum b/electrum @@ -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])] diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -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): @@ -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)) diff --git a/lib/commands.py b/lib/commands.py @@ -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>') @@ -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): diff --git a/lib/transaction.py b/lib/transaction.py @@ -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]) @@ -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 @@ -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 diff --git a/lib/wallet.py b/lib/wallet.py @@ -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) @@ -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): @@ -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):