diff --git a/electrum b/electrum index 2150f6fe7..93f2a9df5 100755 --- a/electrum +++ b/electrum @@ -91,6 +91,7 @@ options:\n --fee, -f: set transaction fee\n --fromaddr, -s: send from address 'unfreeze':'', 'prioritize':'', 'unprioritize':'', + 'dumpprivkey':'', 'createmultisig':'similar to bitcoind\'s command', 'createrawtransaction':'similar to bitcoind\'s command', 'decoderawtransaction':'similar to bitcoind\'s command', @@ -112,7 +113,7 @@ offline_commands = [ 'password', 'mktx', 'signtx', ] -protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage', 'signrawtransaction' ] +protected_commands = ['payto', 'password', 'mktx', 'signtx', 'seed', 'importprivkey','signmessage', 'signrawtransaction','dumpprivkey' ] # get password routine def prompt_password(prompt, confirm=True): @@ -696,6 +697,12 @@ if __name__ == '__main__': print_msg(wallet.unprioritize(addr)) + elif cmd == 'dumpprivkey': + addr = args[1] + sec = wallet.get_private_key_base58(addr, password) + print_msg( sec ) + + elif cmd == 'createmultisig': import ast from lib.bitcoin import * @@ -726,24 +733,34 @@ if __name__ == '__main__': elif cmd == 'signrawtransaction': + import ast tx = Transaction(args[1]) - txouts = args[2] if len(args)>2 else [] - private_keys = args[3] if len(args)>3 else {} + txouts = ast.literal_eval(args[2]) if len(args)>2 else [] + private_keys = ast.literal_eval(args[3]) if len(args)>3 else {} + + # lookup addresses + for txin in tx.inputs: + txid = txin["prevout_hash"] + index = txin["prevout_n"] + utx = wallet.transactions.get(txid) + txout = utx['outputs'][index] + txin['address'] = txout['address'] + txin['raw_output_script'] = txout['raw_output_script'] + # convert to own format + txin['tx_hash'] = txin['prevout_hash'] + txin['index'] = txin['prevout_n'] if not private_keys: for txin in tx.inputs: - txid = txin["prevout_hash"] - index = txin["prevout_n"] - utx = wallet.transactions.get(txid) - txout = utx['outputs'][index] - txin['address'] = txout['address'] - txin['raw_output_script'] = txout['raw_output_script'] - # convert to own format - txin['tx_hash'] = txin['prevout_hash'] - txin['index'] = txin['prevout_n'] - secexp, compressed = wallet.get_private_key(txin['address'], password) - private_keys[addr] = (secexp,compressed) - + addr = txin['address'] + private_keys[addr] = wallet.get_private_key_base58(addr, password) + else: + pk = {} + for sec in private_keys: + address = bitcoin.address_from_private_key(sec) + pk[address] = sec + private_keys = pk + tx.sign( private_keys ) print_msg(tx) diff --git a/lib/bitcoin.py b/lib/bitcoin.py index 970f100ca..f84bd5828 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -232,6 +232,22 @@ def is_compressed(sec): b = ASecretToSecret(sec) return len(b) == 33 + +def address_from_private_key(sec): + # rebuild public key from private key, compressed or uncompressed + pkey = regenerate_key(sec) + assert pkey + + # figure out if private key is compressed + compressed = is_compressed(sec) + + # rebuild private and public key from regenerated secret + private_key = GetPrivKey(pkey, compressed) + public_key = GetPubKey(pkey.pubkey, compressed) + address = public_key_to_bc_address(public_key) + return address + + ########### end pywallet functions ####################### # secp256k1, http://www.oid-info.com/get/1.3.132.0.10 @@ -447,7 +463,11 @@ class Transaction: for i in range(len(self.inputs)): txin = self.inputs[i] - secexp, compressed = private_keys[txin['address']] + sec = private_keys[txin['address']] + compressed = is_compressed(sec) + pkey = regenerate_key(sec) + secexp = pkey.secret + private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) public_key = private_key.get_verifying_key() pkey = EC_KEY(secexp) diff --git a/lib/wallet.py b/lib/wallet.py index df76f8e40..ff00f6636 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -120,19 +120,8 @@ class Wallet: except: raise BaseException("Invalid password") - # rebuild public key from private key, compressed or uncompressed - pkey = regenerate_key(sec) - if not pkey: - return False - - # figure out if private key is compressed - compressed = is_compressed(sec) - - # rebuild private and public key from regenerated secret - private_key = GetPrivKey(pkey, compressed) - public_key = GetPubKey(pkey.pubkey, compressed) - address = public_key_to_bc_address(public_key) - + address = address_from_private_key(sec) + if address in self.all_addresses(): raise BaseException('Address already in wallet')