check if multisig transaction is complete, add is_complete to json output
authorthomasv <thomasv@gitorious>
Sat, 23 Feb 2013 14:11:41 +0000 (15:11 +0100)
committerthomasv <thomasv@gitorious>
Sat, 23 Feb 2013 14:11:41 +0000 (15:11 +0100)
electrum
lib/bitcoin.py

index 12cdb14..07aa6fb 100755 (executable)
--- 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':
index a70c9b5..5f32bc5 100644 (file)
@@ -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 )