Ejemplo n.º 1
0
def tx_from_json_dict(r):
    version = r.get("version")
    lock_time = r.get("locktime")
    txs_in = []
    for vin in r.get("vin"):
        if "coinbase" in vin:
            previous_hash = b'\0' * 32
            script = h2b(vin.get("coinbase"))
            previous_index = 4294967295
        else:
            previous_hash = h2b_rev(vin.get("txid"))
            scriptSig = vin.get("scriptSig")
            if "hex" in scriptSig:
                script = h2b(scriptSig.get("hex"))
            else:
                script = tools.compile(scriptSig.get("asm"))
            previous_index = vin.get("vout")
        sequence = vin.get("sequence")
        txs_in.append(TxIn(previous_hash, previous_index, script, sequence))
    txs_out = []
    for vout in r.get("vout"):
        coin_value = btc_to_satoshi(decimal.Decimal(vout.get("value")))
        script = tools.compile(vout.get("scriptPubKey").get("asm"))
        txs_out.append(TxOut(coin_value, script))
    tx = Tx(version, txs_in, txs_out, lock_time)
    bh = r.get("blockhash")
    if bh:
        bh = h2b_rev(bh)
    tx.confirmation_block_hash = bh
    return tx
Ejemplo n.º 2
0
def tx_from_json_dict(r):
    version = r.get("version")
    lock_time = r.get("locktime")
    txs_in = []
    for vin in r.get("vin"):
        if "coinbase" in vin:
            previous_hash = b'\0' * 32
            script = h2b(vin.get("coinbase"))
            previous_index = 4294967295
        else:
            previous_hash = h2b_rev(vin.get("txid"))
            scriptSig = vin.get("scriptSig")
            if "hex" in scriptSig:
                script = h2b(scriptSig.get("hex"))
            else:
                script = tools.compile(scriptSig.get("asm"))
            previous_index = vin.get("vout")
        sequence = vin.get("sequence")
        txs_in.append(TxIn(previous_hash, previous_index, script, sequence))
    txs_out = []
    for vout in r.get("vout"):
        coin_value = btc_to_satoshi(decimal.Decimal(vout.get("value")))
        script = tools.compile(vout.get("scriptPubKey").get("asm"))
        txs_out.append(TxOut(coin_value, script))
    tx = Tx(version, txs_in, txs_out, lock_time)
    bh = r.get("blockhash")
    if bh:
        bh = h2b_rev(bh)
    tx.confirmation_block_hash = bh
    return tx
Ejemplo n.º 3
0
def main():
    parser = argparse.ArgumentParser(description="Add a transaction to tx cache.")
    parser.add_argument("tx_id_or_path", nargs="+",
                        help='The id of the transaction to fetch from web services or the path to it.')

    args = parser.parse_args()

    TX_RE = re.compile(r"^[0-9a-fA-F]{64}$")

    tx_db = get_tx_db()

    for p in args.tx_id_or_path:
        if TX_RE.match(p):
            tx = tx_db.get(h2b_rev(p))
            if not tx:
                parser.error("can't find Tx with id %s" % p)
        else:
            f = open(p, "rb")
            try:
                if f.name.endswith("hex"):
                    f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                tx = Tx.parse(f)
            except Exception:
                parser.error("can't parse %s" % f.name)

        tx_db[tx.hash()] = tx
        print("cached %s" % tx.id())
Ejemplo n.º 4
0
def parse_tx(arg, parser, tx_db, network):
    # hex transaction id
    tx = None

    if TX_ID_RE.match(arg):
        if tx_db is None:
            tx_db = create_tx_db(network)
        tx = tx_db.get(h2b_rev(arg))
        if not tx:
            parser.error("can't find Tx with id %s" % arg)
        return tx, tx_db

    # hex transaction data
    try:
        return Tx.from_hex(arg), tx_db
    except Exception:
        pass

    if os.path.exists(arg):
        try:
            with open(arg, "rb") as f:
                if f.name.endswith("hex"):
                    f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                tx = Tx.parse(f)
                tx.parse_unspents(f)
        except Exception:
            pass

    return tx, tx_db
Ejemplo n.º 5
0
def populate_unspents(nodes):
    global balance
    global unspents
    
    if nodes['used'] == {}:
        return
    
    addresses = nodes['used'].keys()
    response = json.load( urlopen("http://%s.blockr.io/api/v1/address/unspent/" % BLOCKR + \
                        ','.join(addresses)) )
    data = response['data']
    if type(data) == type({}):
        data = [data]
    
    for entry in data:
        if entry['unspent'] == []:
            continue
        
        for unspent in entry['unspent']:
            balance += Decimal(unspent['amount'])
            amount = convention.btc_to_satoshi(unspent['amount'])
            script = serialize.h2b(unspent['script'])
            txid = serialize.h2b_rev(unspent['tx'])
            
            unspent_spendable = Spendable( amount, script, txid, unspent['n'] )
            unspents.append(unspent_spendable)
            
    time.sleep(1)       # Don't overload blockr.io API
Ejemplo n.º 6
0
 def test_h2b(self):
     h = "000102"
     b = b"\x00\x01\x02"
     self.assertEqual(h2b(h), b)
     self.assertEqual(b2h(b), h)
     self.assertEqual(h2b_rev(h), b[::-1])
     self.assertEqual(b2h_rev(b), "020100")
Ejemplo n.º 7
0
 def decode_spendables(address, results):
     spendables = [
         Spendable(r['value'], ScriptPayToAddress(address),
                   h2b_rev(r['tx_hash']), r['tx_pos'])
         for r in results['result']
     ]
     return spendables
Ejemplo n.º 8
0
def get_tx(tx_hash):
    """
    Get a Tx by its hash.
    """
    # TODO: fix this
    j = get_json_for_hash(tx_hash)
    txs_in = []
    for j_in in j.get("in"):
        if j_in.get("coinbase"):
            txs_in.append(
                TxIn.coinbase_tx_in(binascii.unhexlify(j_in["coinbase"])))
        else:
            txs_in.append(
                TxIn(h2b_rev(j_in["prev_out"]["hash"]),
                     int(j_in["prev_out"]["n"]),
                     tools.compile(j_in["scriptSig"])))

    txs_out = []
    for j_out in j.get("out"):
        txs_out.append(
            TxOut(int(btc_to_satoshi(j_out["value"])),
                  tools.compile(j_out["scriptPubKey"])))

    tx = Tx(int(j["ver"]), txs_in, txs_out, int(j["lock_time"]))
    assert tx.hash() == tx_hash
    return tx
Ejemplo n.º 9
0
 def test_h2b(self):
     h = "000102"
     b = b"\x00\x01\x02"
     self.assertEqual(h2b(h), b)
     self.assertEqual(b2h(b), h)
     self.assertEqual(h2b_rev(h), b[::-1])
     self.assertEqual(b2h_rev(b), "020100")
Ejemplo n.º 10
0
def main():
    parser = argparse.ArgumentParser(
        description="Add a transaction to tx cache.")
    parser.add_argument(
        "tx_id_or_path",
        nargs="+",
        help=
        'The id of the transaction to fetch from web services or the path to it.'
    )

    args = parser.parse_args()

    TX_RE = re.compile(r"^[0-9a-fA-F]{64}$")

    tx_db = get_tx_db()

    for p in args.tx_id_or_path:
        if TX_RE.match(p):
            tx = tx_db.get(h2b_rev(p))
            if not tx:
                parser.error("can't find Transact    ion with id %s" % p)
        else:
            f = open(p, "rb")
            try:
                if f.name.endswith("hex"):
                    f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                tx = Transaction.parse(f)
            except Exception:
                parser.error("can't parse %s" % f.name)

        tx_db[tx.hash()] = tx
        print("cached %s" % tx.id())
Ejemplo n.º 11
0
def parse_tx(arg, parser, tx_db, network):
    # hex transaction id
    tx = None

    if TX_ID_RE.match(arg):
        if tx_db is None:
            tx_db = create_tx_db(network)
        tx = tx_db.get(h2b_rev(arg))
        if not tx:
            parser.error("can't find Tx with id %s" % arg)
        return tx, tx_db

    # hex transaction data
    try:
        return Tx.from_hex(arg), tx_db
    except Exception:
        pass

    if os.path.exists(arg):
        try:
            with open(arg, "rb") as f:
                if f.name.endswith("hex"):
                    f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                tx = Tx.parse(f)
                tx.parse_unspents(f)
        except Exception:
            pass

    return tx, tx_db
Ejemplo n.º 12
0
def main():
    logging.basicConfig(
        level=logging.DEBUG,
        format=('%(asctime)s [%(process)d] [%(levelname)s] '
                '%(filename)s:%(lineno)d %(message)s'))

    from pycoinnet.helpers.networks import MAINNET
    from pycoinnet.util.BlockChainView import BlockChainView
    from pycoinnet.bloom import BloomFilter
    from pycoin.tx import Spendable
    from pycoin.serialize import h2b_rev, h2b
    network = MAINNET
    initial_blockchain_view = BlockChainView()
    bloom_filter = BloomFilter(2048, hash_function_count=8, tweak=3)
    bloom_filter.add_address("14gZfnEn8Xd3ofkjr5s7rKoC3bi8J4Yfyy")
    # bloom_filter.add_address("1GL6i1ty44RnERgqYLKS1CrnhrahW4JhQZ")
    bloom_filter.add_item(h2b("0478abb18c0c7c95348fa77eb5fd43ce963e450d797cf4878894230ca528e6c8e866c3"
                              "8ad93746e04f2161a01787c82a858ee24940e9a06e41fddb3494dfe29380"))
    spendable = Spendable(
        0, b'', h2b_rev("0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9"), 0)
    bloom_filter.add_spendable(spendable)
    merkle_block_index_queue = asyncio.Queue()
    spv = SPVClient(
        network, initial_blockchain_view, bloom_filter, merkle_block_index_queue, host_port_q=None)

    def fetch(merkle_block_index_queue):
        while True:
            merkle_block, index = yield from merkle_block_index_queue.get()
            logging.info(
                "block #%d %s with %d transactions", index, merkle_block.id(), len(merkle_block.txs))

    t = asyncio.Task(fetch(merkle_block_index_queue))

    asyncio.get_event_loop().run_forever()
Ejemplo n.º 13
0
def make_bare_tx(candidate, change_address, rs_asm, version=1):

    # <Tx> components
    spendables = []
    ins = []
    outs = []

    # estimate the final (signed) bytesize per input based on the redeemscript
    redeem_script = tools.compile(rs_asm)
    in_size = estimate_input_size(redeem_script)

    # initialize size and amount counters
    in_amount = Decimal(0)
    est_size = TX_COMPONENTS.version + TX_COMPONENTS.out_count + TX_COMPONENTS.in_count

    # add output size
    est_size += OUTSIZE * 2

    # iterate over unspents
    for utxo in candidate.utxos:

        value = Decimal(utxo.amount) * COIN
        in_amount += value

        script = h2b(utxo.script)
        # for now: test if the in_script we figured we would need, actually matches the in script :D

        # reverse that tx hash
        prevtx = h2b_rev(utxo.hash)

        # output index
        outnum = utxo.outpoint

        # create "spendable"
        spdbl = Spendable(value, script, prevtx, outnum)
        spendables.append(spdbl)

        # also create this as input
        as_input = spdbl.tx_in()
        as_input.sigs = []
        ins.append(as_input)

        # add the estimated size per input
        est_size += in_size

    # calc fee and out amount
    fee = (Decimal(math.ceil(est_size / 1000)) * COIN *
           NETWORK_FEE) + FEE_MARGIN
    change_amount = Decimal(
        math.floor(in_amount - (candidate.amount * COIN) - fee))

    # create outputs
    outs.append(
        TxOut(int(candidate.amount * COIN), make_payto(candidate.address)))
    outs.append(TxOut(int(change_amount), make_payto_script(change_address)))

    # create bare tx without sigs
    tx = Tx(version, ins, outs, 0, spendables)

    return tx
Ejemplo n.º 14
0
	def request_blocks(self, block_ids):
		invs = []
		for id in block_ids:
			inv = bitcoin.net.CInv()
			inv.type = self.INV_BLOCK
			inv.hash = h2b_rev(id)
			invs.append(inv)
		self.request_objects(invs)
 def spendable_for_row(r):
     return Spendable(coin_value=r[2],
                      script=h2b(r[3]),
                      tx_hash=h2b_rev(r[0]),
                      tx_out_index=r[1],
                      block_index_available=r[4],
                      does_seem_spent=r[5],
                      block_index_spent=r[6])
Ejemplo n.º 16
0
 async def get_block(self, blockhash: str, peers=None, timeout=None, privileged_peers=False) -> Dict:
     inv_item = InvItem(ITEM_TYPE_SEGWIT_BLOCK, h2b_rev(blockhash))
     response = await self.pool.get(inv_item, peers=peers, timeout=timeout, privileged=privileged_peers)
     return response and {
         "block_hash": str(blockhash),
         "header_bytes": response[:80],
         "block_bytes": response
     }
Ejemplo n.º 17
0
def get_speendable(address):
    URL = "%s%saddr/%s/utxo" % ('https://test-insight.bitpay.com', '/api/',
                                from_address)
    utxos = json.loads(urlopen(URL).read().decode("utf8"))

    utxo = utxos[0]

    return Spendable(utxo['amount'], h2b(utxo.get("scriptPubKey")),
                     h2b_rev(utxo.get("txid")), utxo.get("vout"))
Ejemplo n.º 18
0
def op_return_this(privatekey, text, prefix = "KEYSTAMP:", bitcoin_fee = 10000):

    bitcoin_keyobj = get_key(privatekey)
    bitcoin_address = bitcoin_keyobj.bitcoin_address()

    ## Get the spendable outputs we are going to use to pay the fee
    all_spendables = get_spendables_blockcypher(bitcoin_address)
    spendables = []
    value = 0
    for unspent in all_spendables:
        while value < bitcoin_fee + 10000:
            coin_value = unspent.get("value")
            script = h2b(unspent.get("script_hex"))
            previous_hash = h2b_rev(unspent.get("tx_hash"))
            previous_index = unspent.get("index")
            spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
            value += coin_value

    bitcoin_sum = sum(spendable.coin_value for spendable in spendables)
    if(bitcoin_sum < bitcoin_fee):
        print "ERROR: not enough balance: available: %s - fee: %s" %(bitcoin_sum, bitcoin_fee)
        return False

    ## Create the inputs we are going to use
    inputs = [spendable.tx_in() for spendable in spendables]
    ## If we will have change left over create an output to send it back
    outputs = []
    if (bitcoin_sum > bitcoin_fee):
        change_output_script = standard_tx_out_script(bitcoin_address)
        total_amout = bitcoin_sum - bitcoin_fee
        outputs.append(TxOut(total_amout, change_output_script))

        # home_address = standard_tx_out_script(bitcoin_address)
        # #TODO: it needs some love and IQ on input mananagement stuff
        # outputs.append(TxOut((bitcoin_sum - bitcoin_fee), home_address))

    ## Build the OP_RETURN output with our message
    if prefix is not None and (len(text) + len(prefix) <= 80):
        text = prefix + text

    message = hexlify(text.encode()).decode('utf8')

    op_return_output_script = tools.compile("OP_RETURN %s" % message)
    outputs.append(TxOut(0, op_return_output_script))

    ## Create the transaction and sign it with the private key
    tx = Tx(version=1, txs_in=inputs, txs_out=outputs)
    # print tx.as_hex()
    # print spendables
    tx.set_unspents(spendables)
    sign_tx(tx, wifs=[privatekey])

    print "singed_tx: %s" %tx.as_hex()

    #TODO: uncomment this when its ready to push data to blockchian
    tx_hash = broadcast_tx_blockr(tx.as_hex())
    return tx_hash
Ejemplo n.º 19
0
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/api/block/%s" % (self.base_url, b2h_rev(block_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     version = r.get("version")
     previous_block_hash = h2b_rev(r.get("previousblockhash"))
     merkle_root = h2b_rev(r.get("merkleroot"))
     timestamp = r.get("time")
     difficulty = int(r.get("bits"), 16)
     nonce = int(r.get("nonce"))
     tx_hashes = [h2b_rev(tx_hash) for tx_hash in r.get("tx")]
     blockheader = BlockHeader(version, previous_block_hash, merkle_root, timestamp, difficulty, nonce)
     if blockheader.hash() != block_hash:
         return None, None
     calculated_hash = merkle(tx_hashes, double_sha256)
     if calculated_hash != merkle_root:
         return None, None
     blockheader.height = r.get("height")
     return blockheader, tx_hashes
Ejemplo n.º 20
0
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/api/block/%s" % (self.base_url, b2h_rev(block_hash))
     r = json.loads(urlopen(URL).read().decode("utf8"))
     version = r.get("version")
     previous_block_hash = h2b_rev(r.get("previousblockhash"))
     merkle_root = h2b_rev(r.get("merkleroot"))
     timestamp = r.get("time")
     difficulty = int(r.get("bits"), 16)
     nonce = int(r.get("nonce"))
     tx_hashes = [h2b_rev(tx_hash) for tx_hash in r.get("tx")]
     blockheader = BlockHeader(version, previous_block_hash, merkle_root, timestamp, difficulty, nonce)
     if blockheader.hash() != block_hash:
         return None, None
     calculated_hash = merkle(tx_hashes, double_sha256)
     if calculated_hash != merkle_root:
         return None, None
     blockheader.height = r.get("height")
     return blockheader, tx_hashes
Ejemplo n.º 21
0
    def spendables_for_address(self, address, amount=None):
        """
        Return a list of Spendable objects for the
        given bitcoin address.
        """
        if amount is None:
            spendables = []
            url_append = "?unspentOnly=true&token=%s&includeScript=true" % self.api_key
            url = self.base_url("addrs/%s%s" % (address, url_append))
            result = json.loads(urlopen(url).read().decode("utf8"))
            for txn in result.get("txrefs", []):
                coin_value = txn.get("value")
                script = h2b(txn.get("script"))
                previous_hash = h2b_rev(txn.get("tx_hash"))
                previous_index = txn.get("tx_output_n")
                spendables.append(
                    Spendable(coin_value, script, previous_hash,
                              previous_index))
            return spendables

        else:
            spendables = []
            url_append = "?unspentOnly=true&token=%s&includeScript=true" % self.api_key
            url = self.base_url("addrs/%s%s" % (address, url_append))
            result = json.loads(urlopen(url).read().decode("utf8"))
            total_amount = 0
            list_spend = result.get("txrefs", [])
            if len(list_spend) == 0:
                raise Exception("No spendable outputs found")
            unspents = sorted(list_spend,
                              key=lambda d: d['value'],
                              reverse=True)
            for txn in unspents:
                coin_value = txn.get("value")
                total_amount = total_amount + coin_value
                script = h2b(txn.get("script"))
                previous_hash = h2b_rev(txn.get("tx_hash"))
                previous_index = txn.get("tx_output_n")
                spendables.append(
                    Spendable(coin_value, script, previous_hash,
                              previous_index))
                if total_amount > amount:
                    break
            return [spendables, total_amount]
Ejemplo n.º 22
0
 def spendables_for_address(self, address, amount=None):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     if amount == None:
         spendables = []
         r = json.loads(
             urlopen(self.base_url('get_tx_unspent',
                                   address)).read().decode("utf8"))
         for u in r['data']['txs']:
             coin_value = int(float(u['value']) * 100000000)
             script = h2b(u["script_hex"])
             previous_hash = h2b_rev(u["txid"])
             previous_index = u["output_no"]
             spendables.append(
                 Spendable(coin_value, script, previous_hash,
                           previous_index))
         return spendables
     else:
         spendables = []
         r = json.loads(
             urlopen(self.base_url('get_tx_unspent',
                                   address)).read().decode("utf8"))
         list_spend = r['data']['txs']
         total_amount = 0
         if len(list_spend) == 0:
             raise Exception("No spendable outputs found")
         unspents = sorted(list_spend,
                           key=lambda d: d['value'],
                           reverse=True)
         for u in unspents:
             coin_value = int(float(u['value']) * 100000000)
             script = h2b(u["script_hex"])
             previous_hash = h2b_rev(u["txid"])
             previous_index = u["output_no"]
             spendables.append(
                 Spendable(coin_value, script, previous_hash,
                           previous_index))
             total_amount = total_amount + coin_value
             if total_amount >= amount:
                 break
         return [spendables, total_amount]
Ejemplo n.º 23
0
 async def get_block(self, blockhash: str, peers=None, timeout=None) -> Dict:
     inv_item = InvItem(ITEM_TYPE_SEGWIT_BLOCK, h2b_rev(blockhash))
     response = await self.pool.get(inv_item, peers=peers, timeout=timeout)
     return response and {
         "block_hash": str(response.hash()),
         "prev_block_hash": str(response.previous_block_hash),
         "timestamp": int(response.timestamp),
         "header_bytes": bytes(response.as_blockheader().as_bin()),
         "block_object": response,
         "block_bytes": bytes(response.as_bin())
     }
Ejemplo n.º 24
0
 def spendables_for_address(self, bitcoin_address):
     URL = "%s/api/addr/%s/utxo" % (self.base_url, bitcoin_address)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r:
         value = btc_to_satoshi(str(u.get("amount")))
         script = h2b(u.get("scriptPubKey"))
         prev_hash = h2b_rev(u.get("txid"))
         prev_index = u.get("vout")
         spendable = Spendable(value, script, prev_hash, prev_index)
         spendables.append(spendable)
     return spendables
Ejemplo n.º 25
0
 def spendables_for_address(self, bitcoin_address):
     url = "{0}/addr/{1}/utxo".format(self.base_url, bitcoin_address)
     result = json.loads(urlopen(url).read().decode("utf8"))
     spendables = []
     for utxo in result:
         value = btc_to_satoshi(str(utxo["amount"]))
         prev_index = utxo["vout"]
         prev_hash = h2b_rev(utxo["txid"])
         script = h2b(utxo["scriptPubKey"])
         spendable = Spendable(value, script, prev_hash, prev_index)
         spendables.append(spendable)
     return spendables
Ejemplo n.º 26
0
 def spendables_for_address(self, bitcoin_address):
     url = "{0}/addr/{1}/utxo".format(self.base_url, bitcoin_address)
     result = json.loads(urlopen(url).read().decode("utf8"))
     spendables = []
     for utxo in result:
         value = btc_to_satoshi(str(utxo["amount"]))
         prev_index = utxo["vout"]
         prev_hash = h2b_rev(utxo["txid"])
         script = h2b(utxo["scriptPubKey"])
         spendable = Spendable(value, script, prev_hash, prev_index)
         spendables.append(spendable)
     return spendables
Ejemplo n.º 27
0
 def spendables_for_address(self, bitcoin_address):
     URL = "%s/api/addr/%s/utxo" % (self.base_url, bitcoin_address)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r:
         value = btc_to_satoshi(str(u.get("amount")))
         script = h2b(u.get("scriptPubKey"))
         prev_hash = h2b_rev(u.get("txid"))
         prev_index = u.get("vout")
         spendable = Spendable(value, script, prev_hash, prev_index)
         spendables.append(spendable)
     return spendables
Ejemplo n.º 28
0
def spend_sh_fund(tx_ins, wif_keys, tx_outs):
    """
    spend script hash fund
    the key point of an input comes from multisig address is that,
    its sign script is combined with several individual signs
    :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script)
    :param wif_keys: private keys in wif format,
        technical should be the same order with the pubkey in redeem script,
        but pycoin has inner control, so here order is not mandatory
    :param tx_outs: balance, receiver_address
    :return: raw hex and tx id
    """
    _txs_in = []
    _un_spent = []
    for tx_id, idx, balance, address, _ in tx_ins:
        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(
            Spendable(
                balance,
                script_obj_from_address(address, netcodes=[NET_CODE]).script(),
                tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(
                balance,
                script_obj_from_address(receiver_address,
                                        netcodes=[NET_CODE]).script()))

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key
    hash160_lookup = build_hash160_lookup(
        [Key.from_text(wif_key).secret_exponent() for wif_key in wif_keys])

    for i in range(0, len(tx_ins)):
        # you can add some conditions that if the input script is not p2sh type, not provide p2sh_lookup,
        # so that all kinds of inputs can work together
        p2sh_lookup = build_p2sh_lookup([binascii.unhexlify(tx_ins[i][-1])])
        tx.sign_tx_in(hash160_lookup,
                      i,
                      tx.unspents[i].script,
                      hash_type=SIGHASH_ALL,
                      p2sh_lookup=p2sh_lookup)

    return tx.as_hex(), tx.id()
Ejemplo n.º 29
0
 def spendables_for_address(self, bitcoin_address, amount=None):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "%s/addr/%s/utxo" % (self.base_url, bitcoin_address)
     print(URL)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     r = sorted(r, key=lambda d: d['amount'], reverse=True)
     if len(r) == 0:
         raise Exception("No spendable outputs found")
     if amount == None:
         spendables = []
         for u in r:
             coin_value = btc_to_satoshi(str(u.get("amount")))
             script = h2b(u.get("scriptPubKey"))
             previous_hash = h2b_rev(u.get("txid"))
             previous_index = u.get("vout")
             spendables.append(
                 Spendable(coin_value, script, previous_hash,
                           previous_index))
         return spendables
     else:
         total_amount = 0
         spendables = []
         for u in r:
             coin_value = btc_to_satoshi(str(u.get("amount")))
             script = h2b(u.get("scriptPubKey"))
             previous_hash = h2b_rev(u.get("txid"))
             previous_index = u.get("vout")
             spendables.append(
                 Spendable(coin_value, script, previous_hash,
                           previous_index))
             total_amount = total_amount + coin_value
             if total_amount >= amount:
                 break
         return [spendables, total_amount]
Ejemplo n.º 30
0
    def validate_unspents(self, tx_db):
        """
        Spendable objects returned from blockchain.info or
        similar services contain coin_value information that must be trusted
        on faith. Mistaken coin_value data can result in coins being wasted
        to fees.

        This function solves this problem by iterating over the incoming
        transactions, fetching them from the tx_db in full, and verifying
        that the coin_values are as expected.

        Returns the fee for this transaction. If any of the spendables set by
        tx.set_unspents do not match the authenticated transactions, a
        ValidationFailureError is raised.
        """
        tx_hashes = set((tx_in.previous_hash for tx_in in self.txs_in))

        # build a local copy of the DB
        tx_lookup = {}
        for h in tx_hashes:
            if h == ZERO32:
                continue
            the_tx = tx_db.get(h)
            if the_tx is None:
                raise KeyError("hash id %s not in tx_db" % b2h_rev(h))
            if the_tx.hash() != h:
                raise KeyError(
                    "attempt to load Tx %s yielded a Tx with id %s" %
                    (h2b_rev(h), the_tx.id()))
            tx_lookup[h] = the_tx

        for idx, tx_in in enumerate(self.txs_in):
            if tx_in.previous_hash == ZERO32:
                continue
            txs_out = tx_lookup[tx_in.previous_hash].txs_out
            if tx_in.previous_index > len(txs_out):
                raise BadSpendableError(
                    "tx_out index %d is too big for Tx %s" %
                    (tx_in.previous_index, b2h_rev(tx_in.previous_hash)))
            tx_out1 = txs_out[tx_in.previous_index]
            tx_out2 = self.unspents[idx]
            if tx_out1.coin_value != tx_out2.coin_value:
                raise BadSpendableError(
                    "unspents[%d] coin value mismatch (%d vs %d)" %
                    (idx, tx_out1.coin_value, tx_out2.coin_value))
            if tx_out1.script != tx_out2.script:
                raise BadSpendableError("unspents[%d] script mismatch!" % idx)

        return self.fee()
Ejemplo n.º 31
0
def spendables_for_address(bitcoin_address):
    """
    Return a list of Spendable objects for the
    given bitcoin address.
    """
    URL = "http://btc.blockr.io/api/v1/address/unspent/%s" % bitcoin_address
    r = json.loads(urlopen(URL).read().decode("utf8"))
    spendables = []
    for u in r.get("data", {}).get("unspent", []):
        coin_value = btc_to_satoshi(u.get("amount"))
        script = h2b(u.get("script"))
        previous_hash = h2b_rev(u.get("tx"))
        previous_index = u.get("n")
        spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
    return spendables
Ejemplo n.º 32
0
 def spendables_for_address(self, bitcoin_address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "%s/api/addr/%s/utxo" % (self.base_url, bitcoin_address)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r:
         coin_value = btc_to_satoshi(u.get("amount"))
         script = h2b(u.get("scriptPubKey"))
         previous_hash = h2b_rev(u.get("txid"))
         previous_index = u.get("vout")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 33
0
 def spendables_for_address(self, bitcoin_address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "%s/api/addr/%s/utxo" % (self.base_url, bitcoin_address)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r:
         coin_value = btc_to_satoshi(str(u.get("amount")))
         script = h2b(u.get("scriptPubKey"))
         previous_hash = h2b_rev(u.get("txid"))
         previous_index = u.get("vout")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 34
0
 def get_unspents(self, address):
     """
     Return a list of Spendable objects for the given bitcoin address.
     """
     URL = "%s/addr/%s/utxo" % (self.base_url, address)
     r = requests.get(URL)
     r.raise_for_status()
     spendables = []
     for u in r.json():
         coin_value = btc_to_satoshi(str(u.get("amount")))
         script = h2b(u.get("scriptPubKey"))
         previous_hash = h2b_rev(u.get("txid"))
         previous_index = u.get("vout")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 35
0
def search(target_xfp):
    k = BIP32Node.from_hwif(
        "tprv8ZgxMBicQKsPeXJHL3vPPgTAEqQ5P2FD9qDeCQT4Cp1EMY5QkwMPWFxHdxHrxZhhcVRJ2m7BNWTz9Xre68y7mX5vCdMJ5qXMUfnrZ2si2X4"
    )

    pid = os.getpid()
    target_xfp = h2b_rev(target_xfp)

    # test by going -33 here.
    #sec_exp = k._secret_exponent - 33
    sec_exp = k._secret_exponent + (pid * int(1e40))

    i = 0
    last_xfp = None
    while 1:
        i += 1
        sec_exp += 1

        public_pair = ecdsa.public_pair_for_secret_exponent(
            ecdsa.generator_secp256k1, sec_exp)

        xfp = public_pair_to_hash160_sec(public_pair, compressed=True)[:4]

        if i <= 5:
            # checking code (slow)
            b = BIP32Node(netcode='BTC',
                          chain_code=bytes(32),
                          secret_exponent=sec_exp)
            chk = b.fingerprint()
            assert b._secret_exponent == sec_exp
            assert xfp == chk, (xfp, chk)

        assert xfp != last_xfp, 'repeat xfp!'
        last_xfp = xfp

        if xfp == target_xfp:
            print(f"\n\nFOUND: sec_exp = {sec_exp}\n")
            b = BIP32Node(netcode='BTC',
                          chain_code=bytes(32),
                          secret_exponent=sec_exp)
            chk = b.fingerprint()
            assert b._secret_exponent == sec_exp
            assert xfp == chk, (xfp, chk)
            print(b.hwif(), end='\n\n')
            return

        if not (i % 27):
            print('  %6d %9d' % (pid, i), end='\r')
Ejemplo n.º 36
0
def txs_from_json(path):
    """
    Read tests from ./data/tx_??valid.json
    Format is an array of arrays
    Inner arrays are either [ "comment" ]
    or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...], serializedTransaction, verifyFlags]
    ... where all scripts are stringified scripts.

    verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
    """
    with open(path, 'r') as f:
        for tvec in json.load(f):
            if len(tvec) == 1:
                continue
            assert len(tvec) == 3
            prevouts = tvec[0]
            for prevout in prevouts:
                assert len(prevout) == 3

            tx_hex = tvec[1]

            flags = set()
            for flag in tvec[2].split(','):
                assert flag in FLAGS
                flags.add(flag)

            try:
                tx = Tx.from_hex(tx_hex)
            except:
                print("Cannot parse tx_hex: %s" % tx_hex)
                raise

            spendable_db = {}
            blank_spendable = Spendable(0, b'', b'\0' * 32, 0)
            for prevout in prevouts:
                spendable = Spendable(coin_value=1000000,
                                      script=compile_script(prevout[2]),
                                      tx_hash=h2b_rev(prevout[0]),
                                      tx_out_index=prevout[1])
                spendable_db[(spendable.tx_hash,
                              spendable.tx_out_index)] = spendable
            unspents = [
                spendable_db.get((tx_in.previous_hash, tx_in.previous_index),
                                 blank_spendable) for tx_in in tx.txs_in
            ]
            tx.set_unspents(unspents)

            yield (tx, flags)
Ejemplo n.º 37
0
    def unspents_for_address(self, address):
        """
        Return a list of Spendable objects for the
        given bitcoin address.
        """
        spendables = []
        r = json.loads(urlopen(self.base_url('get_tx_unspent', address)).read().decode("utf8"))

        for u in r['data']['txs']:
            coin_value = int (float (u['value']) * 100000000)
            script = h2b(u["script_hex"])
            previous_hash = h2b_rev(u["txid"])
            previous_index = u["output_no"]
            spendables.append(Spendable(coin_value, script, previous_hash, previous_index))

        return spendables
Ejemplo n.º 38
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     url_append = "unspent/%s" % address
     URL = "%s/address/%s" % (self.url, url_append)
     r = json.loads(url_open(URL).read().decode("utf8"))
     spendables = []
     for u in r.get("data", {}).get("unspent", []):
         coin_value = btc_to_satoshi(u.get("amount"))
         script = h2b(u.get("script"))
         previous_hash = h2b_rev(u.get("tx"))
         previous_index = u.get("n")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 39
0
def spendables_for_address(bitcoin_address):
    """
    Return a list of Spendable objects for the
    given bitcoin address.
    """
    URL = "http://btc.blockr.io/api/v1/address/unspent/%s" % bitcoin_address
    r = json.loads(urlopen(URL).read().decode("utf8"))
    spendables = []
    for u in r.get("data", {}).get("unspent", []):
        coin_value = btc_to_satoshi(u.get("amount"))
        script = binascii.unhexlify(u.get("script"))
        previous_hash = h2b_rev(u.get("tx"))
        previous_index = u.get("n")
        spendables.append(
            Spendable(coin_value, script, previous_hash, previous_index))
    return spendables
Ejemplo n.º 40
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     spendables = []
     url_append = "?unspentOnly=true&token=%s&includeScript=true" % self.api_key
     url = self.base_url("addrs/%s%s" % (address, url_append))
     result = json.loads(urlopen(url).read().decode("utf8"))
     for txn in result.get("txrefs", []):
         coin_value = txn.get("value")
         script = h2b(txn.get("script"))
         previous_hash = h2b_rev(txn.get("tx_hash"))
         previous_index = txn.get("tx_output_n")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 41
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     url_append = "unspent/%s" % address
     URL = "%s/address/%s" % (self.url, url_append)
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r.get("data", {}).get("unspent", []):
         coin_value = btc_to_satoshi(u.get("amount"))
         script = h2b(u.get("script"))
         previous_hash = h2b_rev(u.get("tx"))
         previous_index = u.get("n")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 42
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     spendables = []
     url_append = "?unspentOnly=true&token=%s&includeScript=true" % self.api_key
     url = self.base_url("addrs/%s%s" % (address, url_append))
     result = json.loads(urlopen(url).read().decode("utf8"))
     for txn in result.get("txrefs", []):
         coin_value = txn.get("value")
         script = h2b(txn.get("script"))
         previous_hash = h2b_rev(txn.get("tx_hash"))
         previous_index = txn.get("tx_output_n")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 43
0
def spendables_for_address(bitcoin_address):
    """
    Return a list of Spendable objects for the
    given bitcoin address.
    """
    json_response = fetch_json("addresses/%s/unspent-outputs" %
                               bitcoin_address)
    spendables = []
    for tx_out_info in json_response.get("data", {}).get("outputs"):
        if tx_out_info.get("to_address") == bitcoin_address:
            coin_value = tx_out_info["value"]
            script = tools.compile(tx_out_info.get("script_pub_key"))
            previous_hash = h2b_rev(tx_out_info.get("transaction_hash"))
            previous_index = tx_out_info.get("transaction_index")
            spendables.append(
                Spendable(coin_value, script, previous_hash, previous_index))
    return spendables
Ejemplo n.º 44
0
def spendables_for_address(bitcoin_address):
    """
    Return a list of Spendable objects for the
    given bitcoin address.
    """
    json_response = fetch_json(
        "addresses/%s/unspent-outputs" % bitcoin_address)
    spendables = []
    for tx_out_info in json_response.get("data", {}).get("outputs"):
        if tx_out_info.get("to_address") == bitcoin_address:
            coin_value = tx_out_info["value"]
            script = tools.compile(tx_out_info.get("script_pub_key"))
            previous_hash = h2b_rev(tx_out_info.get("transaction_hash"))
            previous_index = tx_out_info.get("transaction_index")
            spendables.append(
                Spendable(coin_value, script, previous_hash, previous_index))
    return spendables
Ejemplo n.º 45
0
    def createTransaction(self,
                          address,
                          amount,
                          keychain,
                          fee="standard",
                          confirms=0):
        unspents_result = yield self.unspents()
        spendables = []
        p2sh = []
        chain_paths = []
        # Strip leading /
        keychain_path = keychain['path'][1:]
        for unspent in unspents_result["unspents"]:
            if unspent["confirmations"] < confirms:
                continue
            p2sh.append(h2b(unspent["redeemScript"]))
            spendable = Spendable(unspent["value"], h2b(unspent["script"]),
                                  h2b_rev(unspent["tx_hash"]),
                                  unspent["tx_output_n"])
            spendables.append(spendable)
            chain_paths.append(keychain_path + unspent['chainPath'])
        p2sh_lookup = build_p2sh_lookup(p2sh)
        address_result = yield self.createAddress(1)
        change = address_result["address"]
        tx = tx_utils.create_tx(spendables, [(address, amount), change], fee)

        # address_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path("0/0/0/0"),
        #                 BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(address_result['path'])]

        spendable_keys = [
            BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(path)
            for path in chain_paths
        ]
        # all_keys = address_keys + spendable_keys

        hash160_lookup = build_hash160_lookup(
            [key.secret_exponent() for key in spendable_keys])

        pprint(tx)

        tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        pprint(tx)

        returnValue({'tx': tx.as_hex(), 'fee': tx.fee()})
 async def get_block(self,
                     blockhash: str,
                     peers=None,
                     timeout=None,
                     privileged_peers=False,
                     segwit=True) -> Dict:
     Logger.p2p.debug('Downloading block %s' % blockhash)
     block_type = segwit and ITEM_TYPE_SEGWIT_BLOCK or ITEM_TYPE_BLOCK
     inv_item = InvItem(block_type, h2b_rev(blockhash))
     response = await self.pool.get(inv_item,
                                    peers=peers,
                                    timeout=timeout,
                                    privileged=privileged_peers)
     return response and {
         "block_hash": str(blockhash),
         "header_bytes": response[:80],
         "block_bytes": response
     }
Ejemplo n.º 47
0
 def spendables_for_addresses(self, bitcoin_addresses):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     r = []
     for i in xrange(0, len(bitcoin_addresses), CHUNK_SIZE):
         addresses = bitcoin_addresses[i:i+CHUNK_SIZE]
         url = "%s/api/addrs/%s/utxo" % (self.base_url, ",".join(addresses))
         r.extend(json.loads(urlopen(url).read().decode("utf8")))
     spendables = []
     for u in r:
         coin_value = btc_to_satoshi(str(u.get("amount")))
         script = h2b(u.get("scriptPubKey"))
         previous_hash = h2b_rev(u.get("txid"))
         previous_index = u.get("vout")
         spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Ejemplo n.º 48
0
def txs_from_json(path):
    """
    Read tests from ./data/tx_??valid.json
    Format is an array of arrays
    Inner arrays are either [ "comment" ]
    or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...], serializedTransaction, verifyFlags]
    ... where all scripts are stringified scripts.

    verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
    """
    comments = None
    with open(path, 'r') as f:
        for tvec in json.load(f):
            if len(tvec) == 1:
                comments = tvec[0]
                continue
            assert len(tvec) == 3
            prevouts = tvec[0]
            for prevout in prevouts:
                assert len(prevout) in (3, 4)

            tx_hex = tvec[1]

            flag_mask = parse_flags(tvec[2])
            try:
                tx = Tx.from_hex(tx_hex)
            except:
                print("Cannot parse tx_hex: %s" % tx_hex)
                raise

            spendable_db = {}
            blank_spendable = Spendable(0, b'', b'\0' * 32, 0)
            for prevout in prevouts:
                coin_value = 1000000
                if len(prevout) == 4:
                    coin_value = prevout[3]
                spendable = Spendable(coin_value=coin_value,
                                      script=compile(prevout[2]),
                                      tx_hash=h2b_rev(prevout[0]), tx_out_index=prevout[1])
                spendable_db[(spendable.tx_hash, spendable.tx_out_index)] = spendable
            unspents = [
                spendable_db.get((tx_in.previous_hash, tx_in.previous_index), blank_spendable) for tx_in in tx.txs_in]
            tx.set_unspents(unspents)
            yield (tx, flag_mask, comments)
Ejemplo n.º 49
0
def spendables_for_address(bitcoin_address):
    """
    Return a list of Spendable objects for the
    given bitcoin address.
    """
    URL = "https://api.biteasy.com/blockchain/v1/addresses/%s/unspent-outputs" % bitcoin_address
    r = Request(URL,
                headers={"content-type": "application/json", "accept": "*/*", "User-Agent": "curl/7.29.0"})
    d = urlopen(r).read()
    json_response = json.loads(d.decode("utf8"))
    spendables = []
    for tx_out_info in json_response.get("data", {}).get("outputs"):
        if tx_out_info.get("to_address") == bitcoin_address:
            coin_value = tx_out_info["value"]
            script = tools.compile(tx_out_info.get("script_pub_key"))
            previous_hash = h2b_rev(tx_out_info.get("transaction_hash"))
            previous_index = tx_out_info.get("transaction_index")
            spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
    return spendables
Ejemplo n.º 50
0
    def test_is_invalid(self):
        for (prevouts, tx_hex, flags) in txs_from_json(TX_INVALID_JSON):
            try:
                tx = Tx.from_hex(tx_hex)
                if not check_transaction(tx):
                    continue
                unspents = [Spendable(coin_value=1000000,
                                  script=compile_script(prevout[2]),
                                  tx_hash=h2b_rev(prevout[0]), tx_out_index=prevout[1])
                        for prevout in prevouts]
                tx.set_unspents(unspents)

                bs = tx.bad_signature_count()
                self.assertEqual(bs, 0)
            except:
                continue

            self.fail("Invalid transaction: " + tx.id() +
                      " appears to be valid.")
Ejemplo n.º 51
0
def json_to_tx(json_text):
    # transactions with non-standard lock time are not decoded properly
    # for example, d1ef46055a84fd02ee82580d691064780def18614d98646371c3448ca20019ac
    # there is no way to fix this until biteasy add a lock_time field to their output
    d = json.loads(json_text).get("data")
    txs_in = []
    for d1 in d.get("inputs"):
        previous_hash = h2b_rev(d1.get("outpoint_hash"))
        previous_index = d1.get("outpoint_index")
        script = h2b(d1.get("script_sig"))
        sequence = 4294967295 # BRAIN DAMAGE
        txs_in.append(TxIn(previous_hash, previous_index, script, sequence))
    txs_out = []
    for d1 in d.get("outputs"):
        coin_value = d1.get("value")
        script = h2b(d1.get("script_pub_key"))
        txs_out.append(TxOut(coin_value, script))
    version = d.get("version")
    lock_time = 0 # BRAIN DAMAGE
    return Tx(version, txs_in, txs_out, lock_time)
Ejemplo n.º 52
0
    def createTransaction(self, address, amount, keychain, fee="standard",
                          confirms=0):
        unspents_result = yield self.unspents()
        spendables = []
        p2sh = []
        chain_paths = []
        # Strip leading /
        keychain_path = keychain['path'][1:]
        for unspent in unspents_result["unspents"]:
            if unspent["confirmations"] < confirms:
                continue
            p2sh.append(h2b(unspent["redeemScript"]))
            spendable = Spendable(unspent["value"],
                                  h2b(unspent["script"]),
                                  h2b_rev(unspent["tx_hash"]),
                                  unspent["tx_output_n"])
            spendables.append(spendable)
            chain_paths.append(keychain_path + unspent['chainPath'])
        p2sh_lookup = build_p2sh_lookup(p2sh)
        address_result = yield self.createAddress(1)
        change = address_result["address"]
        tx = tx_utils.create_tx(spendables, [(address, amount), change], fee)

        # address_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path("0/0/0/0"),
        #                 BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(address_result['path'])]

        spendable_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(path) for path in chain_paths]
        # all_keys = address_keys + spendable_keys

        hash160_lookup = build_hash160_lookup([key.secret_exponent() for key in spendable_keys])

        pprint(tx)

        tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        pprint(tx)

        returnValue({'tx': tx.as_hex(),
                     'fee': tx.fee()})
Ejemplo n.º 53
0
def get_tx(tx_hash):
    """
    Get a Tx by its hash.
    """
    # TODO: fix this
    j = get_json_for_hash(tx_hash)
    txs_in = []
    for j_in in j.get("in"):
        if j_in.get("coinbase"):
            txs_in.append(TxIn.coinbase_tx_in(binascii.unhexlify(j_in["coinbase"])))
        else:
            txs_in.append(TxIn(
                h2b_rev(j_in["prev_out"]["hash"]),
                int(j_in["prev_out"]["n"]),
                tools.compile(j_in["scriptSig"])))

    txs_out = []
    for j_out in j.get("out"):
        txs_out.append(TxOut(int(btc_to_satoshi(j_out["value"])), tools.compile(j_out["scriptPubKey"])))

    tx = Tx(int(j["ver"]), txs_in, txs_out, int(j["lock_time"]))
    assert tx.hash() == tx_hash
    return tx
Ejemplo n.º 54
0
    def send(self, wallet_id, passcode, address, amount, message='', fee=10000):
        """
        Send bitcoins to address

        :param wallet_id: bitgo wallet id
        :param address: bitcoin address
        :param amount: btc amount in satoshis
        :return: boolean
        """
        wallet = self.get_wallet(wallet_id)
        if not wallet['spendingAccount']:
            raise NotSpendableWallet()

        if not wallet['isActive']:
            raise NotActiveWallet()

        if amount < 10000:
            raise Exception('amount to small')

        if wallet['confirmedBalance'] < amount:
            raise NotEnoughFunds('Not enough funds: balance %s amount %s' %
                                 (wallet['confirmedBalance'], amount)
            )

        change_address = self.create_address(wallet_id, chain=1)
        usableKeychain = False
        spendables = []
        chain_paths = []
        p2sh = []
        payables = [(address, amount)]
        keychain_path = ""

        for keychain in wallet['private']['keychains']:
            keychain_path = keychain['path'][1:]
            keychain = self.get_keychain(keychain['xpub'])
            if 'encryptedXprv' not in keychain:
                continue
            usableKeychain = True
            break

        if not usableKeychain:
            raise BitGoError("didn't found a spendable keychain")

        data = json.loads(keychain['encryptedXprv'])
        #add base64 paddings
        for k in ['iv', 'salt', 'ct']:
            data[k] = data[k] + "=="
        cipher = sjcl.SJCL()
        xprv = cipher.decrypt(data, passcode)

        unspents = self.get_unspents(wallet_id)
        total_value = 0
        for d in unspents['unspents'][::-1]:
            path = keychain_path + d['chainPath']
            chain_paths.append(path)
            p2sh.append(h2b(d["redeemScript"]))
            spendables.append(Spendable(d["value"],
                                  h2b(d["script"]),
                                  h2b_rev(d["tx_hash"]),
                                  d["tx_output_n"]))

            total_value += d['value']
            if total_value > amount:
                break

        if total_value > (amount + fee):
            #add a change address
            #TODO: create address
            payables.append(change_address)

        p2sh_lookup = build_p2sh_lookup(p2sh)

        spendable_keys = []

        priv_key = BIP32Node.from_hwif(xprv)

        spendable_keys = [priv_key.subkey_for_path(path) for path in chain_paths]

        hash160_lookup = build_hash160_lookup([key.secret_exponent() for key in spendable_keys])

        tx = create_tx(spendables, payables)

        tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        r = requests.post(self.url + '/tx/send', {
                'tx': tx.as_hex(),
                'message': message
            }, headers={
                'Authorization': 'Bearer %s' % self.access_token,
            })

        return r.json()
Ejemplo n.º 55
0
alice_masked_pcode_nosuffix = payment_code_no_suffix(alice_sign, masked_xval, masked_cc)
alice_masked_pcode = pcode_b58( payment_code(alice_sign, masked_xval, masked_cc) )
print "Alice's Masked Payment Code:\n", alice_masked_pcode, '\n'


from pycoin.tx.TxOut import *
from pycoin.tx import Tx, tx_utils, Spendable, pay_to
from pycoin import convention

amount = convention.btc_to_satoshi(first_nondust['amount'])
dustbtc = convention.btc_to_satoshi(DUST)
feebtc = convention.btc_to_satoshi(FEE)

unspent = Spendable( amount, standard_tx_out_script(first_address), \
            serialize.h2b_rev(first_nondust['tx']), first_nondust['n'] )

txout = TxOut( dustbtc, standard_tx_out_script(bob_notif.address()) )
change = TxOut( amount - (dustbtc + feebtc), standard_tx_out_script(change_addresses.pop()) )
op_return_script = pay_to.ScriptNulldata(alice_masked_pcode_nosuffix)
op_return_txout = TxOut(0, op_return_script.script())

notif_tx = Tx( 1, [unspent.tx_in()], [txout, change, op_return_txout], unspents=[unspent] )
tx_utils.sign_tx( notif_tx, [first_node.wif()] )
print "Signed Notification TX as hex:\n", notif_tx.as_hex()

data = urlencode(dict( hex=notif_tx.as_hex() ))
response = json.load( urlopen(url="http://tbtc.blockr.io/api/v1/tx/decode", data=data) )
print "Decoded:\n", pretty_json(response), '\n'

Ejemplo n.º 56
0
def main():
    parser = argparse.ArgumentParser(
        description="Manipulate bitcoin (or alt coin) transactions.",
        epilog=EPILOG)

    parser.add_argument('-t', "--transaction-version", type=int,
                        help='Transaction version, either 1 (default) or 3 (not yet supported).')

    parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block'
                        'index, or a date/time (example: "2014-01-01T15:00:00"')

    parser.add_argument('-n', "--network", default="BTC",
                        help='Define network code (M=Bitcoin mainnet, T=Bitcoin testnet).')

    parser.add_argument('-a', "--augment", action='store_true',
                        help='augment tx by adding any missing spendable metadata by fetching'
                             ' inputs from cache and/or web services')

    parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append",
                        help='Add all unspent spendables for the given bitcoin address. This information'
                        ' is fetched from web services.')

    parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append",
                        help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, '
                        '"gpg -d" will be invoked automatically. File is read one line at a time, and if '
                        'the file contains only one WIF per line, it will also be scanned for a bitcoin '
                        'address, and any addresses found will be assumed to be public keys for the given'
                        ' private key.',
                        type=argparse.FileType('r'))

    parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='')

    parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int,
                        help='remove a tx_in')

    parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int,
                        help='remove a tx_out')

    parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or '
                        '"standard" to auto-calculate. This is only useful if the "split pool" '
                        'is used; otherwise, the fee is automatically set to the unclaimed funds.',
                        default="standard", metavar="transaction-fee", type=parse_fee)

    parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.'
                        ' Mostly for testing.', action='store_true'),

    parser.add_argument('-u', "--show-unspents", action='store_true',
                        help='show TxOut items for this transaction in Spendable form.')

    parser.add_argument('-b', "--bitcoind-url",
                        help='URL to bitcoind instance to validate against (http://user:pass@host:port).')

    parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'),
                        help='file to write transaction to. This supresses most other output.')

    parser.add_argument("argument", nargs="+", help='generic argument: can be a hex transaction id '
                        '(exactly 64 characters) to be fetched from cache or a web service;'
                        ' a transaction as a hex string; a path name to a transaction to be loaded;'
                        ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count '
                        'to be added to TxIn list; an address/satoshi_count to be added to the TxOut '
                        'list; an address to be added to the TxOut list and placed in the "split'
                        ' pool".')

    args = parser.parse_args()

    # defaults

    txs = []
    spendables = []
    payables = []

    key_iters = []

    TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$")

    # there are a few warnings we might optionally print out, but only if
    # they are relevant. We don't want to print them out multiple times, so we
    # collect them here and print them at the end if they ever kick in.

    warning_tx_cache = None
    warning_get_tx = None
    warning_spendables = None

    if args.private_key_file:
        wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}")
        # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}")
        for f in args.private_key_file:
            if f.name.endswith(".gpg"):
                gpg_args = ["gpg", "-d"]
                if args.gpg_argument:
                    gpg_args.extend(args.gpg_argument.split())
                gpg_args.append(f.name)
                popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE)
                f = popen.stdout
            for line in f.readlines():
                # decode
                if isinstance(line, bytes):
                    line = line.decode("utf8")
                # look for WIFs
                possible_keys = wif_re.findall(line)

                def make_key(x):
                    try:
                        return Key.from_text(x)
                    except Exception:
                        return None

                keys = [make_key(x) for x in possible_keys]
                for key in keys:
                    if key:
                        key_iters.append((k.wif() for k in key.subkeys("")))

                # if len(keys) == 1 and key.hierarchical_wallet() is None:
                #    # we have exactly 1 WIF. Let's look for an address
                #   potential_addresses = address_re.findall(line)

    # we create the tx_db lazily
    tx_db = None

    for arg in args.argument:

        # hex transaction id
        if TX_ID_RE.match(arg):
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx = tx_db.get(h2b_rev(arg))
            if not tx:
                for m in [warning_tx_cache, warning_get_tx, warning_spendables]:
                    if m:
                        print("warning: %s" % m, file=sys.stderr)
                parser.error("can't find Tx with id %s" % arg)
            txs.append(tx)
            continue

        # hex transaction data
        try:
            tx = Tx.tx_from_hex(arg)
            txs.append(tx)
            continue
        except Exception:
            pass

        try:
            key = Key.from_text(arg)
            # TODO: check network
            if key.wif() is None:
                payables.append((key.address(), 0))
                continue
            # TODO: support paths to subkeys
            key_iters.append((k.wif() for k in key.subkeys("")))
            continue
        except Exception:
            pass

        if os.path.exists(arg):
            try:
                with open(arg, "rb") as f:
                    if f.name.endswith("hex"):
                        f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                    tx = Tx.parse(f)
                    txs.append(tx)
                    try:
                        tx.parse_unspents(f)
                    except Exception as ex:
                        pass
                    continue
            except Exception:
                pass

        parts = arg.split("/")
        if len(parts) == 4:
            # spendable
            try:
                spendables.append(Spendable.from_text(arg))
                continue
            except Exception:
                pass

        # TODO: fix allowable_prefixes
        allowable_prefixes = b'\0'
        if len(parts) == 2 and encoding.is_valid_bitcoin_address(
                parts[0], allowable_prefixes=allowable_prefixes):
            try:
                payables.append(parts)
                continue
            except ValueError:
                pass

        parser.error("can't parse %s" % arg)

    if args.fetch_spendables:
        warning_spendables = message_about_spendables_for_address_env()
        for address in args.fetch_spendables:
            spendables.extend(spendables_for_address(address))

    for tx in txs:
        if tx.missing_unspents() and args.augment:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx.unspents_from_db(tx_db, ignore_missing=True)

    txs_in = []
    txs_out = []
    unspents = []
    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    lock_time = args.lock_time
    version = args.transaction_version

    # if no lock_time is explicitly set, inherit from the first tx or use default
    if lock_time is None:
        if txs:
            lock_time = txs[0].lock_time
        else:
            lock_time = DEFAULT_LOCK_TIME

    # if no version is explicitly set, inherit from the first tx or use default
    if version is None:
        if txs:
            version = txs[0].version
        else:
            version = DEFAULT_VERSION

    if args.remove_tx_in:
        s = set(args.remove_tx_in)
        txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s]

    if args.remove_tx_out:
        s = set(args.remove_tx_out)
        txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s]

    tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents)

    fee = args.fee
    try:
        distribute_from_split_pool(tx, fee)
    except ValueError as ex:
        print("warning: %s" % ex.args[0], file=sys.stderr)

    unsigned_before = tx.bad_signature_count()
    if unsigned_before > 0 and key_iters:
        def wif_iter(iters):
            while len(iters) > 0:
                for idx, iter in enumerate(iters):
                    try:
                        wif = next(iter)
                        yield wif
                    except StopIteration:
                        iters = iters[:idx] + iters[idx+1:]
                        break

        print("signing...", file=sys.stderr)
        sign_tx(tx, wif_iter(key_iters))

    unsigned_after = tx.bad_signature_count()
    if unsigned_after > 0 and key_iters:
        print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr)

    if len(tx.txs_in) == 0:
        print("warning: transaction has no inputs", file=sys.stderr)

    if len(tx.txs_out) == 0:
        print("warning: transaction has no outputs", file=sys.stderr)

    include_unspents = (unsigned_after > 0)
    tx_as_hex = tx.as_hex(include_unspents=include_unspents)

    if args.output_file:
        f = args.output_file
        if f.name.endswith(".hex"):
            f.write(tx_as_hex.encode("utf8"))
        else:
            tx.stream(f)
            if include_unspents:
                tx.stream_unspents(f)
        f.close()
    elif args.show_unspents:
        for spendable in tx.tx_outs_as_spendable():
            print(spendable.as_text())
    else:
        if not tx.missing_unspents():
            check_fees(tx)
        dump_tx(tx, args.network)
        if include_unspents:
            print("including unspents in hex dump since transaction not fully signed")
        print(tx_as_hex)

    if args.cache:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_get_tx = message_about_get_tx_env()
            tx_db = get_tx_db()
        tx_db.put(tx)

    if args.bitcoind_url:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_get_tx = message_about_get_tx_env()
            tx_db = get_tx_db()
        validate_bitcoind(tx, tx_db, args.bitcoind_url)

    if tx.missing_unspents():
        print("\n** can't validate transaction as source transactions missing", file=sys.stderr)
    else:
        try:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx.validate_unspents(tx_db)
            print('all incoming transaction values validated')
        except BadSpendableError as ex:
            print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr)
        except Exception as ex:
            print("\n*** can't validate source transactions as untampered: %s" %
                  ex.args[0], file=sys.stderr)

    # print warnings
    for m in [warning_tx_cache, warning_get_tx, warning_spendables]:
        if m:
            print("warning: %s" % m, file=sys.stderr)
 def spendable_for_row(r):
     return Spendable(coin_value=r[2], script=h2b(r[3]), tx_hash=h2b_rev(r[0]), tx_out_index=r[1],
                      block_index_available=r[4], does_seem_spent=r[5], block_index_spent=r[6])
Ejemplo n.º 58
0
 def get_blockchain_tip(self):
     URL = "%s/api/status?q=getLastBlockHash" % self.base_url
     d = urlopen(URL).read().decode("utf8")
     r = json.loads(d)
     return h2b_rev(r.get("lastblockhash"))
Ejemplo n.º 59
0
    def test_validate(self):
        # block 80971
        block_80971_cs = h2b('00000000001126456C67A1F5F0FF0268F53B4F22E0531DC70C7B69746AF69DAC')
        block_80971_data = h2b('01000000950A1631FB9FAC411DFB173487B9E18018B7C6F7147E78C06258410000000000A881352F97F14B'\
        'F191B54915AE124E051B8FE6C3922C5082B34EAD503000FC34D891974CED66471B4016850A040100'\
        '0000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF080'\
        '4ED66471B02C301FFFFFFFF0100F2052A01000000434104CB6B6B4EADC96C7D08B21B29D0ADA5F29F937'\
        '8978CABDB602B8B65DA08C8A93CAAB46F5ABD59889BAC704925942DD77A2116D10E0274CAD944C71D3D1A'\
        '670570AC0000000001000000018C55ED829F16A4E43902940D3D33005264606D5F7D555B5F67EE4C033390'\
        'C2EB010000008A47304402202D1BF606648EDCDB124C1254930852D99188E1231715031CBEAEA80CCFD2B39A'\
        '02201FA9D6EE7A1763580E342474FC1AEF59B0468F98479953437F525063E25675DE014104A01F763CFBF5E518'\
        'C628939158AF3DC0CAAC35C4BA7BC1CE8B7E634E8CDC44E15F0296B250282BD649BAA8398D199F2424FCDCD88'\
        'D3A9ED186E4FD3CB9BF57CFFFFFFFFF02404B4C00000000001976A9148156FF75BEF24B35ACCE3C05289A241'\
        '1E1B0E57988AC00AA38DF010000001976A914BC7E692A5FFE95A596712F5ED83393B3002E452E88AC000000'\
        '0001000000019C97AFDF6C9A31FFA86D71EA79A079001E2B59EE408FD418498219400639AC0A010000008B4'\
        '830450220363CFFAE09599397B21E6D8A8073FB1DFBE06B6ACDD0F2F7D3FEA86CA9C3F605022100FA255A6ED'\
        '23FD825C759EF1A885A31CAD0989606CA8A3A16657D50FE3CEF5828014104FF444BAC08308B9EC97F56A652A'\
        'D8866E0BA804DA97868909999566CB377F4A2C8F1000E83B496868F3A282E1A34DF78565B65C15C3FA21A076'\
        '3FD81A3DFBBB6FFFFFFFF02C05EECDE010000001976A914588554E6CC64E7343D77117DA7E01357A6111B798'\
        '8AC404B4C00000000001976A914CA6EB218592F289999F13916EE32829AD587DBC588AC00000000010000000'\
        '1BEF5C9225CB9FE3DEF929423FA36AAD9980B9D6F8F3070001ACF3A5FB389A69F000000004A493046022100F'\
        'B23B1E2F2FB8B96E04D220D385346290A9349F89BBBC5C225D5A56D931F8A8E022100F298EB28294B90C1BAF'\
        '319DAB713E7CA721AAADD8FCC15F849DE7B0A6CF5412101FFFFFFFF0100F2052A010000001976A9146DDEA80'\
        '71439951115469D0D2E2B80ECBCDD48DB88AC00000000');

        # block 80974
        block_80974_cs = h2b('0000000000089F7910F6755C10EA2795EC368A29B435D80770AD78493A6FECF1')
        block_80974_data = h2b('010000007480150B299A16BBCE5CCDB1D1BBC65CFC5893B01E6619107C55200000000000790'\
        '0A2B203D24C69710AB6A94BEB937E1B1ADD64C2327E268D8C3E5F8B41DBED8796974CED66471B204C3247030'\
        '1000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0804ED6'\
        '6471B024001FFFFFFFF0100F2052A010000004341045FEE68BAB9915C4EDCA4C680420ED28BBC369ED84D48A'\
        'C178E1F5F7EEAC455BBE270DABA06802145854B5E29F0A7F816E2DF906E0FE4F6D5B4C9B92940E4F0EDAC000'\
        '000000100000001F7B30415D1A7BF6DB91CB2A272767C6799D721A4178AA328E0D77C199CB3B57F010000008'\
        'A4730440220556F61B84F16E637836D2E74B8CB784DE40C28FE3EF93CCB7406504EE9C7CAA5022043BD4749D'\
        '4F3F7F831AC696748AD8D8E79AEB4A1C539E742AA3256910FC88E170141049A414D94345712893A828DE57B4C'\
        '2054E2F596CDCA9D0B4451BA1CA5F8847830B9BE6E196450E6ABB21C540EA31BE310271AA00A49ED0BA930743'\
        'D1ED465BAD0FFFFFFFF0200E1F505000000001976A914529A63393D63E980ACE6FA885C5A89E4F27AA08988AC'\
        'C0ADA41A000000001976A9145D17976537F308865ED533CCCFDD76558CA3C8F088AC000000000100000001651'\
        '48D894D3922EF5FFDA962BE26016635C933D470C8B0AB7618E869E3F70E3C000000008B48304502207F5779EB'\
        'F4834FEAEFF4D250898324EB5C0833B16D7AF4C1CB0F66F50FCF6E85022100B78A65377FD018281E77285EFC3'\
        '1E5B9BA7CB7E20E015CF6B7FA3E4A466DD195014104072AD79E0AA38C05FA33DD185F84C17F611E58A8658CE'\
        '996D8B04395B99C7BE36529CAB7606900A0CD5A7AEBC6B233EA8E0FE60943054C63620E05E5B85F0426FFFFF'\
        'FFF02404B4C00000000001976A914D4CAA8447532CA8EE4C80A1AE1D230A01E22BFDB88AC8013A0DE0100000'\
        '01976A9149661A79AE1F6D487AF3420C13E649D6DF3747FC288AC00000000')

        block_80971 = Block.parse(io.BytesIO(block_80971_data))
        block_80974 = Block.parse(io.BytesIO(block_80974_data))

        tx_db = dict((tx.hash(), tx) for tx in block_80971.txs)

        tx_to_validate = block_80974.txs[2]
        self.assertEqual("OP_DUP OP_HASH160 d4caa8447532ca8ee4c80a1ae1d230a01e22bfdb OP_EQUALVERIFY OP_CHECKSIG",
            tools.disassemble(tx_to_validate.txs_out[0].script))
        self.assertEqual(tx_to_validate.hash(), h2b_rev("7c4f5385050c18aa8df2ba50da566bbab68635999cc99b75124863da1594195b"))

        tx_to_validate.validate(tx_db)

        # now, let's corrupt the Tx and see what happens
        tx_out = tx_to_validate.txs_out[1]

        disassembly = tools.disassemble(tx_out.script)

        tx_out.script = tools.compile(disassembly)

        tx_to_validate.validate(tx_db)

        disassembly = disassembly.replace("9661a79ae1f6d487af3420c13e649d6df3747fc2", "9661a79ae1f6d487af3420c13e649d6df3747fc3")

        tx_out.script = tools.compile(disassembly)

        with self.assertRaises(ValidationFailureError) as cm:
            tx_to_validate.validate(tx_db)
        exception = cm.exception
        self.assertEqual(exception.args[0], "Tx 3c0ef7e369e81876abb0c870d433c935660126be62a9fd5fef22394d898d1465 TxIn index 0 did not verify")
Ejemplo n.º 60
0
Archivo: tx.py Proyecto: Zibbo/pycoin
def parse_context(args, parser):
    # defaults

    txs = []
    spendables = []
    payables = []

    key_iters = []

    TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$")

    # there are a few warnings we might optionally print out, but only if
    # they are relevant. We don't want to print them out multiple times, so we
    # collect them here and print them at the end if they ever kick in.

    warning_tx_cache = None
    warning_tx_for_tx_hash = None
    warning_spendables = None

    if args.private_key_file:
        wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}")
        # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}")
        for f in args.private_key_file:
            if f.name.endswith(".gpg"):
                gpg_args = ["gpg", "-d"]
                if args.gpg_argument:
                    gpg_args.extend(args.gpg_argument.split())
                gpg_args.append(f.name)
                popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE)
                f = popen.stdout
            for line in f.readlines():
                # decode
                if isinstance(line, bytes):
                    line = line.decode("utf8")
                # look for WIFs
                possible_keys = wif_re.findall(line)

                def make_key(x):
                    try:
                        return Key.from_text(x)
                    except Exception:
                        return None

                keys = [make_key(x) for x in possible_keys]
                for key in keys:
                    if key:
                        key_iters.append((k.wif() for k in key.subkeys("")))

                # if len(keys) == 1 and key.hierarchical_wallet() is None:
                #    # we have exactly 1 WIF. Let's look for an address
                #   potential_addresses = address_re.findall(line)

    # update p2sh_lookup
    p2sh_lookup = {}
    if args.pay_to_script:
        for p2s in args.pay_to_script:
            try:
                script = h2b(p2s)
                p2sh_lookup[hash160(script)] = script
            except Exception:
                print("warning: error parsing pay-to-script value %s" % p2s)

    if args.pay_to_script_file:
        hex_re = re.compile(r"[0-9a-fA-F]+")
        for f in args.pay_to_script_file:
            count = 0
            for l in f:
                try:
                    m = hex_re.search(l)
                    if m:
                        p2s = m.group(0)
                        script = h2b(p2s)
                        p2sh_lookup[hash160(script)] = script
                        count += 1
                except Exception:
                    print("warning: error parsing pay-to-script file %s" % f.name)
            if count == 0:
                print("warning: no scripts found in %s" % f.name)

    # we create the tx_db lazily
    tx_db = None

    for arg in args.argument:

        # hex transaction id
        if TX_ID_RE.match(arg):
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network)
                tx_db = get_tx_db(args.network)
            tx = tx_db.get(h2b_rev(arg))
            if not tx:
                for m in [warning_tx_cache, warning_tx_for_tx_hash, warning_spendables]:
                    if m:
                        print("warning: %s" % m, file=sys.stderr)
                parser.error("can't find Tx with id %s" % arg)
            txs.append(tx)
            continue

        # hex transaction data
        try:
            tx = Tx.from_hex(arg)
            txs.append(tx)
            continue
        except Exception:
            pass

        is_valid = is_address_valid(arg, allowable_netcodes=[args.network])
        if is_valid:
            payables.append((arg, 0))
            continue

        try:
            key = Key.from_text(arg)
            # TODO: check network
            if key.wif() is None:
                payables.append((key.address(), 0))
                continue
            # TODO: support paths to subkeys
            key_iters.append((k.wif() for k in key.subkeys("")))
            continue
        except Exception:
            pass

        if os.path.exists(arg):
            try:
                with open(arg, "rb") as f:
                    if f.name.endswith("hex"):
                        f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                    tx = Tx.parse(f)
                    txs.append(tx)
                    try:
                        tx.parse_unspents(f)
                    except Exception as ex:
                        pass
                    continue
            except Exception:
                pass

        parts = arg.split("/")
        if len(parts) == 4:
            # spendable
            try:
                spendables.append(Spendable.from_text(arg))
                continue
            except Exception:
                pass

        if len(parts) == 2 and is_address_valid(parts[0], allowable_netcodes=[args.network]):
            try:
                payables.append(parts)
                continue
            except ValueError:
                pass

        parser.error("can't parse %s" % arg)

    if args.fetch_spendables:
        warning_spendables = message_about_spendables_for_address_env(args.network)
        for address in args.fetch_spendables:
            spendables.extend(spendables_for_address(address))

    for tx in txs:
        if tx.missing_unspents() and args.augment:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network)
                tx_db = get_tx_db(args.network)
            tx.unspents_from_db(tx_db, ignore_missing=True)

    return (txs, spendables, payables, key_iters, p2sh_lookup, tx_db, warning_tx_cache,
            warning_tx_for_tx_hash, warning_spendables)