From bd8dbbf79b2f13045b53234a093be04dd648d3a9 Mon Sep 17 00:00:00 2001 From: thomasv Date: Sat, 23 Feb 2013 15:11:41 +0100 Subject: [PATCH] check if multisig transaction is complete, add is_complete to json output --- electrum | 2 +- lib/bitcoin.py | 46 ++++++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/electrum b/electrum index 12cdb1428..07aa6fb5f 100755 --- a/electrum +++ b/electrum @@ -788,7 +788,7 @@ if __name__ == '__main__': private_keys = pk tx.sign( private_keys ) - print_msg(tx) + print_json({ "hex":str(tx),"complete":tx.is_complete}) elif cmd == 'listunspent': diff --git a/lib/bitcoin.py b/lib/bitcoin.py index a70c9b572..5f32bc54a 100644 --- a/lib/bitcoin.py +++ b/lib/bitcoin.py @@ -601,29 +601,42 @@ class Transaction: # list of already existing signatures signatures = txin.get("signatures",[]) - - # check if we have a key corresponding to the redeem script found = False - for pubkey, privkey in keypairs.items(): - if pubkey in redeem_pubkeys: - # add signature - 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() - - tx = raw_tx( self.inputs, self.outputs, for_sig = i ) - sig = private_key.sign_digest( Hash( tx.decode('hex') ), sigencode = ecdsa.util.sigencode_der ) - assert public_key.verify_digest( sig, Hash( tx.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der) - signatures.append( sig.encode('hex') ) - found = True + complete = True + # check if we have a key corresponding to the redeem script + for pubkey in redeem_pubkeys: + public_key = ecdsa.VerifyingKey.from_string(pubkey[2:].decode('hex'), curve = SECP256k1) + tx_for_sig = raw_tx( self.inputs, self.outputs, for_sig = i ) + + for s in signatures: + try: + public_key.verify_digest( s.decode('hex')[:-1], Hash( tx_for_sig.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der) + break + except ecdsa.keys.BadSignatureError: + continue + else: + if pubkey in keypairs.keys(): + # add signature + sec = keypairs[pubkey] + 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() + 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') ) + found = True + else: + complete = False + if not found: raise BaseException("public key not found", keypairs.keys(), redeem_pubkeys) # for p2sh, pubkeysig is a tuple (may be incomplete) self.inputs[i]["signatures"] = signatures + self.is_complete = complete else: sec = private_keys[txin['address']] @@ -640,6 +653,7 @@ class Transaction: assert public_key.verify_digest( sig, Hash( tx.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der) self.inputs[i]["pubkeysig"] = [(pubkey, sig)] + self.is_complete = True self.raw = raw_tx( self.inputs, self.outputs )