URI: 
       ttransaction: add_signature(), is_complete() methods - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit f550b452bebc47af473ced0d82f379188f23e7a5
   DIR parent 94829db701515e4d7b44167408852877680b2572
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Mon,  7 Apr 2014 11:03:12 +0200
       
       ttransaction: add_signature(), is_complete() methods
       
       Diffstat:
         M gui/qt/main_window.py               |       2 +-
         M lib/transaction.py                  |      52 ++++++++++++++++++-------------
       
       2 files changed, 32 insertions(+), 22 deletions(-)
       ---
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -920,7 +920,7 @@ class ElectrumWindow(QMainWindow):
                if label:
                    self.wallet.set_label(tx.hash(), label)
        
       -        if not tx.is_complete:
       +        if not tx.is_complete():
                    self.show_transaction(tx)
                    return
        
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -377,7 +377,7 @@ class Transaction:
                self.outputs = self.d['outputs']
                self.outputs = map(lambda x: (x['address'],x['value']), self.outputs)
                self.locktime = self.d['lockTime']
       -        self.is_complete = is_complete
       +
                
            def __str__(self):
                return self.raw
       t@@ -386,7 +386,6 @@ class Transaction:
            def from_io(klass, inputs, outputs):
                raw = klass.serialize(inputs, outputs, for_sig = -1) # for_sig=-1 means do not sign
                self = klass(raw)
       -        self.is_complete = False
                self.inputs = inputs
                self.outputs = outputs
                return self
       t@@ -487,17 +486,37 @@ class Transaction:
                return s
        
        
       -    def for_sig(self,i):
       +    def tx_for_sig(self,i):
                return self.serialize(self.inputs, self.outputs, for_sig = i)
        
        
            def hash(self):
                return Hash(self.raw.decode('hex') )[::-1].encode('hex')
        
       +    def add_signature(self, i, pubkey, sig):
       +        txin = self.inputs[i]
       +        signatures = txin.get("signatures",{})
       +        signatures[pubkey] = sig
       +        txin["signatures"] = signatures
       +        self.inputs[i] = txin
       +        print_error("adding signature for", pubkey)
       +        self.raw = self.serialize( self.inputs, self.outputs )
       +
       +
       +    def is_complete(self):
       +        for i, txin in enumerate(self.inputs):
       +            redeem_script = txin.get('redeemScript')
       +            num, redeem_pubkeys = parse_redeemScript(redeem_script) if redeem_script else (1, [txin.get('redeemPubkey')])
       +            signatures = txin.get("signatures",{})
       +            if len(signatures) == num:
       +                continue
       +            else:
       +                return False
       +        return True
       +
        
        
            def sign(self, keypairs):
       -        is_complete = True
                print_error("tx.sign(), keypairs:", keypairs)
        
                for i, txin in enumerate(self.inputs):
       t@@ -514,34 +533,25 @@ class Transaction:
                    if len(signatures) == num:
                        continue
        
       -            tx_for_sig = self.serialize( self.inputs, self.outputs, for_sig = i )
       -
       -            print_error("redeem pubkeys input %d"%i, redeem_pubkeys)
       +            for_sig = Hash(self.tx_for_sig(i).decode('hex'))
                    for pubkey in redeem_pubkeys:
       -                # check if we have the corresponding private key
                        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_deterministic( Hash( tx_for_sig.decode('hex') ), hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der )
       -                    assert public_key.verify_digest( sig, Hash( tx_for_sig.decode('hex') ), sigdecode = ecdsa.util.sigdecode_der)
       +                    sig = private_key.sign_digest_deterministic( for_sig, hashfunc=hashlib.sha256, sigencode = ecdsa.util.sigencode_der )
       +                    assert public_key.verify_digest( sig, for_sig, sigdecode = ecdsa.util.sigdecode_der)
       +                    self.add_signature(i, pubkey, sig.encode('hex'))
        
       -                    # insert signature in the list
       -                    signatures[pubkey] = sig.encode('hex')
       -                    print_error("adding signature for", pubkey)
       -            
       -            txin["signatures"] = signatures
       -            is_complete = is_complete and len(signatures) == num
        
       -        print_error("is_complete", is_complete)
       -        self.is_complete = is_complete
       +        print_error("is_complete", self.is_complete())
                self.raw = self.serialize( self.inputs, self.outputs )
        
        
       +
            def deserialize(self):
                vds = BCDataStream()
                vds.write(self.raw.decode('hex'))
       t@@ -691,10 +701,10 @@ class Transaction:
                import json
                out = {
                    "hex":self.raw,
       -            "complete":self.is_complete
       +            "complete":self.is_complete()
                    }
        
       -        if not self.is_complete:
       +        if not self.is_complete():
                    input_info = self.get_input_info()
                    out['input_info'] = json.dumps(input_info).replace(' ','')