URI: 
       tfix createrawtransaction, using extended serialization format - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 52e9c0b4988e928a95623834c826d1145a52b422
   DIR parent 3d32bba0b9570916c3a433d5c3737079b8f56c3f
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Mon, 29 Dec 2014 20:26:00 +0100
       
       fix createrawtransaction, using extended serialization format
       
       Diffstat:
         M lib/commands.py                     |      19 ++++++++++++++-----
         M lib/transaction.py                  |     122 +++++++++++++------------------
       
       2 files changed, 66 insertions(+), 75 deletions(-)
       ---
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -65,7 +65,7 @@ verifymessage_syntax = 'verifymessage <address> <signature> <message>\nIf you wa
        register_command('contacts',             0, 0, False, True,  False, 'Show your list of contacts')
        register_command('create',               0, 0, False, True,  False, 'Create a new wallet')
        register_command('createmultisig',       2, 2, False, True,  False, 'similar to bitcoind\'s command')
       -register_command('createrawtransaction', 2, 2, False, True,  False, 'similar to bitcoind\'s command')
       +register_command('createrawtransaction', 2, 2, False, True,  False, 'Create an unsigned transaction. The syntax is similar to bitcoind.')
        register_command('deseed',               0, 0, False, True,  False, 'Remove seed from wallet, creating a seedless, watching-only wallet.')
        register_command('decoderawtransaction', 1, 1, False, False, False, 'similar to bitcoind\'s command')
        register_command('getprivatekeys',       1, 1, False, True,  True,  'Get the private keys of a given address', 'getprivatekeys <bitcoin address>')
       t@@ -158,11 +158,20 @@ class Commands:
                    return {'address':r[0] }
        
            def createrawtransaction(self, inputs, outputs):
       +        coins = self.wallet.get_unspent_coins(None)
       +        tx_inputs = []
                for i in inputs:
       -            i['prevout_hash'] = i['txid']
       -            i['prevout_n'] = i['vout']
       -        outputs = map(lambda x: (x[0],int(1e8*x[1])), outputs.items())
       -        tx = Transaction(inputs, outputs)
       +            prevout_hash = i['txid']
       +            prevout_n = i['vout']
       +            for c in coins:
       +                if c['prevout_hash'] == prevout_hash and c['prevout_n'] == prevout_n:
       +                    self.wallet.add_input_info(c)
       +                    tx_inputs.append(c)
       +                    break
       +            else:
       +                raise BaseException('Transaction output not in wallet', prevout_hash+":%d"%prevout_n)
       +        outputs = map(lambda x: ('address', x[0], int(1e8*x[1])), outputs.items())
       +        tx = Transaction(tx_inputs, outputs)
                return tx
        
            def signtxwithkey(self, raw_tx, sec):
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -204,24 +204,6 @@ def short_hex(bytes):
        
        
        
       -
       -def parse_redeemScript(bytes):
       -    dec = [ x for x in script_GetOp(bytes.decode('hex')) ]
       -
       -    # 2 of 2
       -    match = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_2, opcodes.OP_CHECKMULTISIG ]
       -    if match_decoded(dec, match):
       -        pubkeys = [ dec[1][1].encode('hex'), dec[2][1].encode('hex') ]
       -        return 2, pubkeys
       -
       -    # 2 of 3
       -    match = [ opcodes.OP_2, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4, opcodes.OP_3, opcodes.OP_CHECKMULTISIG ]
       -    if match_decoded(dec, match):
       -        pubkeys = [ dec[1][1].encode('hex'), dec[2][1].encode('hex'), dec[3][1].encode('hex') ]
       -        return 2, pubkeys
       -
       -
       -
        opcodes = Enumeration("Opcodes", [
            ("OP_0", 0), ("OP_PUSHDATA1",76), "OP_PUSHDATA2", "OP_PUSHDATA4", "OP_1NEGATE", "OP_RESERVED",
            "OP_1", "OP_2", "OP_3", "OP_4", "OP_5", "OP_6", "OP_7",
       t@@ -581,12 +563,12 @@ class Transaction:
        
        
            @classmethod
       -    def pay_script(self, type, addr):
       -        if type == 'op_return':
       +    def pay_script(self, output_type, addr):
       +        if output_type == 'op_return':
                    h = addr.encode('hex')
                    return '6a' + push_script(h)
                else:
       -            assert type == 'address'
       +            assert output_type == 'address'
                addrtype, hash_160 = bc_address_to_hash_160(addr)
                if addrtype == 0:
                    script = '76a9'                                      # op_dup, op_hash_160
       t@@ -600,70 +582,70 @@ class Transaction:
                    raise
                return script
        
       -
       -    def serialize(self, for_sig=None):
       +    def input_script(self, txin, i, for_sig):
                # for_sig:
                #   -1   : do not sign, estimate length
                #   i>=0 : serialized tx for signing input i
                #   None : add all known signatures
        
       +        p2sh = txin.get('redeemScript') is not None
       +        num_sig = txin['num_sig'] if p2sh else 1
       +        address = txin['address']
       +
       +        x_signatures = txin['signatures']
       +        signatures = filter(None, x_signatures)
       +        is_complete = len(signatures) == num_sig
       +
       +        if for_sig in [-1, None]:
       +            # if we have enough signatures, we use the actual pubkeys
       +            # use extended pubkeys (with bip32 derivation)
       +            if for_sig == -1:
       +                # we assume that signature will be 0x48 bytes long
       +                pubkeys = txin['pubkeys']
       +                sig_list = [ "00" * 0x48 ] * num_sig
       +            elif is_complete:
       +                pubkeys = txin['pubkeys']
       +                sig_list = ((sig + '01') for sig in signatures)
       +            else:
       +                pubkeys = txin['x_pubkeys']
       +                sig_list = ((sig + '01') if sig else NO_SIGNATURE for sig in x_signatures)
       +            script = ''.join(push_script(x) for x in sig_list)
       +            if not p2sh:
       +                x_pubkey = pubkeys[0]
       +                if x_pubkey is None:
       +                    addrtype, h160 = bc_address_to_hash_160(txin['address'])
       +                    x_pubkey = 'fd' + (chr(addrtype) + h160).encode('hex')
       +                script += push_script(x_pubkey)
       +            else:
       +                script = '00' + script          # put op_0 in front of script
       +                redeem_script = self.multisig_script(pubkeys,2)
       +                script += push_script(redeem_script)
       +
       +        elif for_sig==i:
       +            script = txin['redeemScript'] if p2sh else self.pay_script('address', address)
       +        else:
       +            script = ''
       +
       +        return script
       +
       +
       +    def serialize(self, for_sig=None):
                inputs = self.inputs
                outputs = self.outputs
       -
                s  = int_to_hex(1,4)                                         # version
                s += var_int( len(inputs) )                                  # number of inputs
                for i, txin in enumerate(inputs):
       -
                    s += txin['prevout_hash'].decode('hex')[::-1].encode('hex')   # prev hash
       -            s += int_to_hex(txin['prevout_n'],4)                          # prev index
       -
       -            p2sh = txin.get('redeemScript') is not None
       -            num_sig = txin['num_sig']
       -            address = txin['address']
       -
       -            x_signatures = txin['signatures']
       -            signatures = filter(None, x_signatures)
       -            is_complete = len(signatures) == num_sig
       -
       -            if for_sig in [-1, None]:
       -                # if we have enough signatures, we use the actual pubkeys
       -                # use extended pubkeys (with bip32 derivation)
       -                if for_sig == -1:
       -                    # we assume that signature will be 0x48 bytes long
       -                    pubkeys = txin['pubkeys']
       -                    sig_list = [ "00" * 0x48 ] * num_sig
       -                elif is_complete:
       -                    pubkeys = txin['pubkeys']
       -                    sig_list = ((sig + '01') for sig in signatures)
       -                else:
       -                    pubkeys = txin['x_pubkeys']
       -                    sig_list = ((sig + '01') if sig else NO_SIGNATURE for sig in x_signatures)
       -                script = ''.join(push_script(x) for x in sig_list)
       -                if not p2sh:
       -                    x_pubkey = pubkeys[0]
       -                    if x_pubkey is None:
       -                        addrtype, h160 = bc_address_to_hash_160(txin['address'])
       -                        x_pubkey = 'fd' + (chr(addrtype) + h160).encode('hex')
       -                    script += push_script(x_pubkey)
       -                else:
       -                    script = '00' + script          # put op_0 in front of script
       -                    redeem_script = self.multisig_script(pubkeys,2)
       -                    script += push_script(redeem_script)
       -
       -            elif for_sig==i:
       -                script = txin['redeemScript'] if p2sh else self.pay_script('address', address)
       -            else:
       -                script = ''
       -
       +            s += int_to_hex(txin['prevout_n'], 4)                         # prev index
       +            script = self.input_script(txin, i, for_sig)
                    s += var_int( len(script)/2 )                            # script length
                    s += script
                    s += "ffffffff"                                          # sequence
       -
                s += var_int( len(outputs) )                                 # number of outputs
                for output in outputs:
       -            type, addr, amount = output
       +            output_type, addr, amount = output
                    s += int_to_hex( amount, 8)                              # amount
       -            script = self.pay_script(type, addr)
       +            script = self.pay_script(output_type, addr)
                    s += var_int( len(script)/2 )                           #  script length
                    s += script                                             #  script
                s += int_to_hex(0,4)                                        #  lock time
       t@@ -696,9 +678,9 @@ class Transaction:
                for txin in self.inputs:
                    if txin.get('is_coinbase'):
                        continue
       -            signatures = filter(None, txin['signatures'])
       +            signatures = filter(None, txin.get('signatures',[]))
                    s += len(signatures)
       -            r += txin['num_sig']
       +            r += txin.get('num_sig',-1)
                return s, r
        
            def is_complete(self):