import io, struct, os, sys, math
from binascii import crc32, unhexlify, hexlify
from bitcoin.main import *
from bitcoin.bci import *
from bitcoin.transaction import *
from bitcoin.pyspecials import safe_hexlify, safe_unhexlify, st, by

def mk_multisig_scriptpubkey(fo):
    # takes file_object fo and returns scriptpubkey as hex
    data = fo.read(65*3)

    if not data:
        return None
    
    script_pubkeys = []
    while data:
        chunk = data[:65]; data = data[65:]
        # pad right side with null bytes
        if len(chunk) < 33:   chunk += b'\x00' * (33-len(chunk))
        elif len(chunk) < 65: chunk += b'\x00' * (65-len(chunk))
        script_pubkeys.append(chunk)

    pubz = list(map(safe_hexlify, script_pubkeys))
    return mk_multisig_script(pubz, 1)
 
def mk_txouts(fo, value=None, jsonfmt=1):
    """Make Tx Outputs as json (or hex)"""
    value = 547 if not value else int(value)
    txouts = []
    while True:
        scriptPubKey = mk_multisig_scriptpubkey(fo)
        if scriptPubKey is None: break
        txouts.append( {'script': scriptPubKey, 'value': value} )
    if jsonfmt:
        return txouts
    return ''.join([(safe_hexlify(struct.pack('<Q', value)) +
                     str(wrap_script(x['script']))) for x in txouts])

def mk_binary_txouts(filename, value=None, jsonfmt=1):
    """Encode file into the blockchain (with prepended file length, crc32) using multisig addresses"""
    try: fileobj = open(filename, 'rb').read()
    except: raise Exception("can't find file!")

    data = struct.pack('<I', len(fileobj)) + \
           struct.pack('<I', crc32(fileobj) & 0xffffffff) + fileobj
    fd = io.BytesIO(data)
    TXOUTS = mk_txouts(fd, value, jsonfmt)
    if jsonfmt:
        return list(TXOUTS)
    return wrap_varint(TXOUTS)

def encode_file(filename, privkey, value=None, input_address=None, network=None):
    """Takes binary file, returns signed Tx"""
    if not network:
        network = 'testnet'

    if input_address is None:
        input_address = privtoaddr(privkey, 111) if network == 'testnet' else privtoaddr(privkey)

    u = blockr_unspent(input_address, 'testnet') if network == 'testnet' else unspent(input_address)
    value = 547 if value is None else int(value)
    TXFEE = int(math.ceil(1.1 * (10000*os.path.getsize(filename)/1000)))
    OUTS = mk_binary_txouts(filename, value)
    TOTALFEE = TXFEE + int(value)*len(OUTS)
    INS = select(u, TOTALFEE)

    rawtx = mksend(INS, OUTS, input_address, TXFEE)
    signedtx = sign(rawtx, 0, privkey, 1)
    return signedtx


def decode_file(txid, network='btc'):
    """Returns decoded blockchain binary file as bytes, ready to write to a file"""
    # TODO: multiple TxIDs? verify encode_file output? 
    assert network in ('btc', 'testnet')
    
    rawtx = blockr_fetchtx(txid, network)
    txo = deserialize(rawtx)
    outs1 = map(deserialize_script, multiaccess(txo['outs'], 'script'))
    
    # get hex key data from multisig scripts
    outs2 = filter(lambda l: l[-1] == 174, outs1)		# TODO: need to check for non-p2sh outputs
    outs3 = map(lambda l: l[1:-2], outs2)

    data = safe_unhexlify(''.join([item for sublist in outs3 for item in sublist]))	# base 256 of encoded data
    
    # TODO: need to check if the length and crc32 are appended
    length = struct.unpack('<I', data[0:4])[0]		# TODO: need to check length matches filesize in bytes
    checksum = struct.unpack('<I', data[4:8])[0]
	
    data = data[8:8+length]
    
    assert checksum == crc32(data) & 0xffffffff	 

    # TODO: write return to file object?
    return data

def decode_files(txids, network='btc'):
    if isinstance(txids, string_types):
        return decode_file(txids, network)
    elif isinstance(txids, list) and len(txid) == 1:
        return decode_file(txids[0], network)
    return ''.join([decode_file(x) for x in txids])
	
# if __name__ == '__main__':
#     import sys, os
#     if len(sys.argv) < 2: 
#         print("mk_binary_txouts.py FILENAME OUTPUT_VALUE [INPUT_ADDRESS]")
#     elif len(sys.argv) == 3:
#         filename = sys.argv[-1]     # TODO: check file exists
#     elif len(sys.argv) == 4:

@@ -229,16 +229,17 @@
 st, by%0A%0A
+%0A
 def mk_m
@@ -274,60 +274,43 @@
   # 
-takes file_object fo and returns scriptpubkey as hex
+make a single output's redeemScript
 %0A   
@@ -369,21 +369,17 @@
 rn None%0A
-    
 %0A
+
     scri
@@ -535,25 +535,27 @@
 unk += b
-'%5Cx00' * 
+y(bytearray
 (33-len(
@@ -553,32 +553,33 @@
 y(33-len(chunk))
+)
 %0A        elif le
@@ -607,20 +607,22 @@
 += b
-'%5Cx00' * (65
+y(bytearray(33
 -len
@@ -629,16 +629,17 @@
 (chunk))
+)
 %0A       
@@ -759,18 +759,17 @@
 ubz, 1)%0A
- 
 %0A
+
 def mk_t
@@ -886,24 +886,100 @@
  int(value)%0A
+    hexval = safe_hexlify(struct.pack('%3CQ', value))%09# make 8 byte LE value %0A
     txouts =
@@ -1218,69 +1218,16 @@
 n(%5B(
-safe_hexlify(struct.pack('%3CQ', value)) +%0A                    
+hexval +
  str
@@ -2240,24 +2240,25 @@
  int(value)%0A
+%0A
     TXFEE = 
@@ -3751,16 +3751,17 @@
 len(txid
+s
 ) == 1:%0A
@@ -3861,17 +3861,16 @@
 ds%5D)%0A%09%0A#
- 
 if __nam
@@ -3892,29 +3892,8 @@
 _':%0A
-#     import sys, os%0A
 #   

Update file_insert.py