From 81b84fd5efc5a573c71779d4fca80f24afc87871 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sat, 17 Aug 2013 18:40:59 +0200 Subject: [PATCH] fixes for signrawtransaction --- electrum | 3 ++- lib/bitcoin.py | 6 +++-- lib/wallet.py | 60 ++++++++++++++++++++++++-------------------------- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/electrum b/electrum index 1646d898..6de03f1f 100755 --- a/electrum +++ b/electrum @@ -429,7 +429,8 @@ if __name__ == '__main__': try: result = func(*args[1:]) except BaseException, e: - print_msg("Error: " + str(e)) + import traceback + traceback.print_exc(file=sys.stdout) sys.exit(1) if type(result) == str: diff --git a/lib/bitcoin.py b/lib/bitcoin.py index 28eb31bc..67c36fd9 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -604,6 +604,9 @@ class Transaction: redeem_script = txin.get('redeemScript') num, redeem_pubkeys = deserialize.parse_redeemScript(redeem_script) if redeem_script else (1, [txin.get('redeemPubkey')]) + # add pubkeys + txin["pubkeys"] = redeem_pubkeys + # get list of already existing signatures signatures = txin.get("signatures",[]) # continue if this txin is complete @@ -624,9 +627,8 @@ class Transaction: sig = private_key.sign_digest( Hash( tx_for_sig.decode('hex') ), sigencode = ecdsa.util.sigencode_der ) assert public_key.verify_digest( sig, Hash( tx_for_sig.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der) signatures.append( sig.encode('hex') ) - + txin["signatures"] = signatures - txin["pubkeys"] = redeem_pubkeys print_error("signatures", signatures) is_complete = is_complete and len(signatures) == num diff --git a/lib/wallet.py b/lib/wallet.py index b3c684ff..d1133283 100644 --- a/lib/wallet.py +++ b/lib/wallet.py @@ -356,6 +356,16 @@ class Wallet: return dd + def get_keyID(self, account, sequence): + rs = self.rebase_sequence(account, sequence) + dd = [] + for root, public_sequence in rs: + c, K, _ = self.master_public_keys[root] + s = '/' + '/'.join( map(lambda x:str(x), public_sequence) ) + dd.append( 'bip32(%s,%s,%s)'%(c,K, s) ) + return '&'.join(dd) + + def get_public_key(self, address): account, sequence = self.get_address_index(address) return self.accounts[account].get_pubkey( *sequence ) @@ -414,27 +424,27 @@ class Wallet: else: for item in unspent_coins: if txin['tx_hash'] == item['tx_hash'] and txin['index'] == item['index']: + print_error( "tx input is in unspent coins" ) txin['raw_output_script'] = item['raw_output_script'] + account, sequence = self.get_address_index(item['address']) + if account != -1: + txin['redeemScript'] = self.accounts[account].redeem_script(sequence) break else: - # if neither, we might want to get it from the server.. - raise + raise BaseException("Unknown transaction input. Please provide the 'input_info' parameter, or synchronize this wallet") - # find the address and fill private_keys + # if available, derive private_keys from KeyID keyid = txin.get('KeyID') if keyid: - roots = [] for s in keyid.split('&'): m = re.match("bip32\(([0-9a-f]+),([0-9a-f]+),(/\d+/\d+/\d+)", s) if not m: continue - c = m.group(1) K = m.group(2) sequence = m.group(3) root = self.find_root_by_master_key(c,K) if not root: continue - sequence = map(lambda x:int(x), sequence.strip('/').split('/')) root = root + '%d'%sequence[0] sequence = sequence[1:] @@ -451,18 +461,22 @@ class Wallet: keypairs[pubkey] = sec redeem_script = txin.get("redeemScript") + print_error( "p2sh:", "yes" if redeem_script else "no") if redeem_script: - num, redeem_pubkeys = deserialize.parse_redeemScript(redeem_script) addr = hash_160_to_bc_address(hash_160(redeem_script.decode('hex')), 5) - txin['address'] = addr + else: + addr = deserialize.get_address_from_output_script(txin["raw_output_script"].decode('hex')) + txin['address'] = addr - elif txin.get("raw_output_script"): - addr = deserialize.get_address_from_output_script(txin.get("raw_output_script").decode('hex')) - sec = self.get_private_key(addr, password) + # add private keys that are in the wallet + pk = self.get_private_key(addr, password) + for sec in pk: pubkey = public_key_from_private_key(sec) - if sec: - keypairs[pubkey] = sec - txin['address'] = addr + keypairs[pubkey] = sec + if not redeem_script: + txin['redeemPubkey'] = pubkey + + print txin tx.sign( keypairs ) @@ -948,13 +962,6 @@ class Wallet: def mktx(self, outputs, password, fee=None, change_addr=None, account=None ): - """ - create a transaction - account parameter: - None means use all accounts - -1 means imported keys - 0, 1, etc are seed accounts - """ for address, x in outputs: assert is_valid(address) @@ -973,15 +980,7 @@ class Wallet: address = txin['address'] account, sequence = self.get_address_index(address) - - rs = self.rebase_sequence(account, sequence) - dd = [] - for root, public_sequence in rs: - c, K, _ = self.master_public_keys[root] - s = '/' + '/'.join( map(lambda x:str(x), public_sequence) ) - dd.append( 'bip32(%s,%s,%s)'%(c,K, s) ) - - txin['KeyID'] = '&'.join(dd) + txin['KeyID'] = self.get_keyID(account, sequence) redeemScript = self.accounts[account].redeem_script(sequence) if redeemScript: @@ -992,7 +991,6 @@ class Wallet: private_keys = self.get_private_key(address, password) - print "pk", address, private_keys for sec in private_keys: pubkey = public_key_from_private_key(sec) keypairs[ pubkey ] = sec