Example #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 = BitcoinScriptTools.compile(scriptSig.get("asm"))
            previous_index = vin.get("vout")
        sequence = vin.get("sequence")
        txs_in.append(Tx.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 = BitcoinScriptTools.compile(vout.get("scriptPubKey").get("asm"))
        txs_out.append(Tx.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
Example #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 = BitcoinScriptTools.compile(scriptSig.get("asm"))
            previous_index = vin.get("vout")
        sequence = vin.get("sequence")
        txs_in.append(Tx.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 = BitcoinScriptTools.compile(
            vout.get("scriptPubKey").get("asm"))
        txs_out.append(Tx.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
Example #3
0
def spend_pkh_fund(tx_ins, in_keys, tx_outs):
    """
    p2pkh address send to p2pkh p2sh transaction
    :param tx_ins: list with tuple(tx_id, idx, balance, address)
    :param in_keys: list of private keys in hex format corresponding to each input
    :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))

        script = network.contract.for_address(address)
        _un_spent.append(Spendable(balance, script, tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(balance, network.contract.for_address(receiver_address)))

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

    solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys],
                                  [secp256k1_generator])
    tx.sign(solver, hash_type=SIGHASH_ALL)

    return tx.as_hex(), tx.id()
Example #4
0
def tether_tx(tx_ins, in_keys, send_amount, receiver, change_address):
    """
    simple usdt transaction

    different address's utxo can be used for mine fee,
    but should be aware sender is determined by the first input in the tx

    bitcoin change can also be sent back to different address,
    but should be aware receiver is indicated by the last output address that is not the sender

    :param tx_ins: utxo from the sender
    :param in_keys: list of private keys in hex format corresponding to each input
    :param send_amount: (display amount) * (10 ** 8)
    :param receiver: address to receive usdt
    :param change_address: address to receive btc change
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address in tx_ins:
        total_bal += balance

        # 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, network.contract.for_address(address), tx_id_b,
                      idx))

    satoshi_per_byte = recommend_satoshi_per_byte()
    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * satoshi_per_byte

    _txs_out = [
        TxOut(total_bal - txn_fee - MIN_BTC_OUT,
              network.contract.for_address(change_address)),
        TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
        TxOut(MIN_BTC_OUT, network.contract.for_address(receiver))
    ]

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

    solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys],
                                  [secp256k1_generator])
    signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL)

    return signed_tx.as_hex(), signed_tx.id()
Example #5
0
 def tx_for_tx_hash(self, tx_hash):
     """
     Get a Tx by its hash.
     """
     url = "%s/rawtx/%s" % (self.url, b2h_rev(tx_hash))
     d = urlopen(url).read()
     j = json.loads(d.decode("utf8"))
     tx = Tx.from_hex(j.get("rawtx", ""))
     if tx.hash() == tx_hash:
         return tx
Example #6
0
 def tx_for_tx_hash(self, tx_hash):
     """
     Get a Tx by its hash.
     """
     url = "%s/rawtx/%s" % (self.url, b2h_rev(tx_hash))
     d = urlopen(url).read()
     j = json.loads(d.decode("utf8"))
     tx = Tx.from_hex(j.get("rawtx", ""))
     if tx.hash() == tx_hash:
         return tx
Example #7
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, network.contract.for_address(address), tx_id_b,
                      idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(balance, network.contract.for_address(receiver_address)))

    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(
        [network.parse.wif(wif_key).secret_exponent() for wif_key in wif_keys],
        [secp256k1_generator])

    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])])
        r = BitcoinSolver(tx).solve(hash160_lookup,
                                    i,
                                    hash_type=SIGHASH_ALL,
                                    p2sh_lookup=p2sh_lookup)
        if isinstance(r, bytes):
            tx.txs_in[i].script = r
        else:
            tx.txs_in[i].script = r[0]
            tx.set_witness(i, r[1])

    return tx.as_hex(), tx.id()
Example #8
0
 def tx_for_tx_hash(self, tx_hash):
     """
     returns the pycoin.tx object for tx_hash
     """
     try:
         url_append = "?token=%s&includeHex=true" % self.api_key
         url = self.base_url("txs/%s%s" % (b2h_rev(tx_hash), url_append))
         result = json.loads(urlopen(url).read().decode("utf8"))
         tx = Tx.parse(io.BytesIO(h2b(result.get("hex"))))
         return tx
     except Exception:
         raise Exception
Example #9
0
 def tx_for_tx_hash(self, tx_hash):
     """
     returns the pycoin.tx object for tx_hash
     """
     try:
         url_append = "?token=%s&includeHex=true" % self.api_key
         url = self.base_url("txs/%s%s" % (b2h_rev(tx_hash), url_append))
         result = json.loads(urlopen(url).read().decode("utf8"))
         tx = Tx.parse(io.BytesIO(h2b(result.get("hex"))))
         return tx
     except Exception:
         raise Exception
Example #10
0
def tether_tx_flush(tx_ins, private_key, send_amount, receiver):
    """
    this is just a tool function that sends all btc and usdt fund to the same receiver address
    params are same with tether_tx
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address in tx_ins:
        total_bal += balance

        # 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, network.contract.for_address(address), tx_id_b,
                      idx))

    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins),
                                      2) * recommend_satoshi_per_byte()

    _txs_out = [
        TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
        TxOut(total_bal - txn_fee, network.contract.for_address(receiver))
    ]

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

    solver = build_hash160_lookup([int(private_key, 16)] * len(tx_ins),
                                  [secp256k1_generator])
    signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL)

    return signed_tx.as_hex(), signed_tx.id()
Example #11
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "https://blockchain.info/unspent?active=%s" % address
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r["unspent_outputs"]:
         coin_value = u["value"]
         script = h2b(u["script"])
         previous_hash = h2b(u["tx_hash"])
         previous_index = u["tx_output_n"]
         spendables.append(
             Tx.Spendable(coin_value, script, previous_hash,
                          previous_index))
     return spendables
Example #12
0
 def get(self, key):
     for path in self.paths_for_hash(key):
         try:
             tx = Tx.parse(open(path, "rb"))
             if tx and tx.hash() == key:
                 return tx
         except IOError:
             pass
     for method in self.lookup_methods:
         try:
             tx = method(key)
             if tx and tx.hash() == key:
                 self.put(tx)
                 return tx
         except Exception:
             pass
     return None
Example #13
0
 def get(self, key):
     for path in self.paths_for_hash(key):
         try:
             tx = Tx.parse(open(path, "rb"))
             if tx and tx.hash() == key:
                 return tx
         except IOError:
             pass
     for method in self.lookup_methods:
         try:
             tx = method(key)
             if tx and tx.hash() == key:
                 self.put(tx)
                 return tx
         except Exception:
             pass
     return None
Example #14
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "%s/addr/%s/utxo" % (self.base_url, 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(
             Tx.Spendable(coin_value, script, previous_hash,
                          previous_index))
     return spendables
Example #15
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(
             Tx.Spendable(coin_value, script, previous_hash,
                          previous_index))
     return spendables
    def parse(self, raw):
        # auto-detect and decode Base64 and Hex.
        if raw[0:10].lower() == b'70736274ff':
            raw = a2b_hex(raw.strip())
        if raw[0:6] == b'cHNidP':
            raw = b64decode(raw)
        assert raw[0:5] == b'psbt\xff', "bad magic"

        with io.BytesIO(raw[5:]) as fd:
            
            # globals
            while 1:
                ks = deser_compact_size(fd)
                if ks is None: break

                if ks == 0: break

                key = fd.read(ks)
                vs = deser_compact_size(fd)
                val = fd.read(vs)

                kt = key[0]
                if kt == PSBT_GLOBAL_UNSIGNED_TX:
                    self.txn = val

                    t = Tx.parse(io.BytesIO(val))
                    num_ins = len(t.txs_in)
                    num_outs = len(t.txs_out)
                elif kt == PSBT_GLOBAL_XPUB:
                    self.xpubs[key[1:]] = val
                else:
                    raise ValueError('unknown global key type: 0x%02x' % kt)

            assert self.txn, 'missing reqd section'

            self.inputs = [BasicPSBTInput(fd, idx) for idx in range(num_ins)]
            self.outputs = [BasicPSBTOutput(fd, idx) for idx in range(num_outs)]

            sep = fd.read(1)
            assert sep == b''

        return self
Example #17
0
    def spendables_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(
                Tx.Spendable(coin_value, script, previous_hash,
                             previous_index))

        return spendables
Example #18
0
def tether_tx_sh(tx_ins, wif_keys, send_amount, receiver, change_address):
    """
    spend usdt having p2sh utxo
    WARNING!!! THIS FUNCTION IS NOT FULLY TESTED AS MY FUND WAS STOLEN BY A SON OF BITCH
        AFTER I BY ACCIDENT COMMITTED MY PRIVATE KEY!!!
    :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script),
        redeem_script is required for p2sh utxo, set it None for p2pkh utxo
    :param wif_keys: private keys of the inputs
    :param send_amount: (display amount) * (10 ** 8)
    :param receiver: address to receive usdt
    :param change_address: address to receive btc change
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address, _ in tx_ins:
        total_bal += balance

        # 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, network.contract.for_address(address), tx_id_b,
                      idx))

    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins),
                                      3) * recommend_satoshi_per_byte() / 3

    _txs_out = [
        TxOut(total_bal - txn_fee - MIN_BTC_OUT,
              network.contract.for_address(change_address)),
        TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
        TxOut(MIN_BTC_OUT, network.contract.for_address(receiver))
    ]

    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(
        [network.parse.wif(wif_key).secret_exponent() for wif_key in wif_keys],
        [secp256k1_generator])

    for i in range(0, len(tx_ins)):
        if tx_ins[i][-1]:
            p2sh_lookup = build_p2sh_lookup(
                [binascii.unhexlify(tx_ins[i][-1])])
        else:
            p2sh_lookup = None

        r = BitcoinSolver(tx).solve(hash160_lookup,
                                    i,
                                    hash_type=SIGHASH_ALL,
                                    p2sh_lookup=p2sh_lookup)
        if isinstance(r, bytes):
            tx.txs_in[i].script = r
        else:
            tx.txs_in[i].script = r[0]
            tx.set_witness(i, r[1])

    return tx.as_hex(), tx.id()
Example #19
0
 def tx_for_tx_hash(self, tx_hash):
     raw_tx = self.connection.getrawtransaction(b2h_rev(tx_hash))
     tx = Tx.from_hex(raw_tx)
     return tx
Example #20
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     URL = "https://blockchain.info/rawtx/%s?format=hex" % b2h_rev(tx_hash)
     tx = Tx.from_hex(urlopen(URL).read().decode("utf8"))
     return tx
Example #21
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     url = self.base_url("get_tx", b2h_rev(tx_hash))
     r = json.loads(urlopen(url).read().decode("utf8"))
     tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx_hex"))))
     return tx
Example #22
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     URL = self.api_domain + ("/rawtx/%s?format=hex" % b2h_rev(tx_hash))
     tx = Tx.from_hex(urlopen(URL).read().decode("utf8"))
     return tx
Example #23
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     url = self.base_url("get_tx", b2h_rev(tx_hash))
     r = json.loads(urlopen(url).read().decode("utf8"))
     tx = Tx.parse(io.BytesIO(h2b(r.get("data").get("tx_hex"))))
     return tx
Example #24
0
 def tx_for_tx_hash(self, tx_hash):
     raw_tx = self.connection.getrawtransaction(b2h_rev(tx_hash))
     tx = Tx.from_hex(raw_tx)
     return tx
Example #25
0
 def tx_for_tx_hash(self, tx_hash):
     "Get a Tx by its hash."
     URL = self.api_domain + ("/rawtx/%s?format=hex" % b2h_rev(tx_hash))
     tx = Tx.from_hex(urlopen(URL).read().decode("utf8"))
     return tx
Example #26
0
def build_psbt(ctx, xfp, addrs, pubkey=None, xpubs=None, redeem=None):
    locals().update(ctx.obj)
    payout_address = ctx.obj['payout_address']
    out_psbt = ctx.obj['output_psbt']

    if pubkey:
        assert len(addrs) == 1  # can only be single addr in that case
        assert len(pubkey) == 33

    spending = []
    total = 0
    psbt = BasicPSBT()

    for path, addr in addrs:
        print(f"addr: {path} => {addr} ... ", end='')

        rr = explora('address', addr, 'utxo')

        if not rr:
            print('nada')
            continue

        here = 0
        for u in rr:
            here += u['value']

            tt = TxIn(h2b_rev(u['txid']), u['vout'])
            spending.append(tt)
            #print(rr)

            pin = BasicPSBTInput(idx=len(psbt.inputs))
            psbt.inputs.append(pin)

            pubkey = pubkey or calc_pubkey(xpubs, path)

            pin.bip32_paths[pubkey] = str2path(xfp, path)

            # fetch the UTXO for witness signging
            td = explora('tx', u['txid'], 'hex', is_json=False)

            #print(f"txis {u['txid']}:\b{td!r}")
            outpt = Tx.from_hex(td.decode('ascii')).txs_out[u['vout']]

            with BytesIO() as b:
                outpt.stream(b)
                pin.witness_utxo = b.getvalue()

            if redeem:
                pin.redeem_script = redeem

        print('%.8f BTC' % (here / 1E8))
        total += here

        if len(spending) > 15:
            print("Reached practical limit on # of inputs. "
                  "You'll need to repeat this process again later.")
            break

    assert total, "Sorry! Didn't find any UTXO"

    print("Found total: %.8f BTC" % (total / 1E8))

    if payout_address:
        print("Planning to send to: %s" % payout_address)
        dest_scr = BTC.contract.for_address(payout_address)

        txn = Tx(2, spending, [TxOut(total, dest_scr)])
    else:
        print("Output section of PSBT will be empty. Change downstream")
        txn = Tx(2, spending, [])

    fee = tx_fee.recommended_fee_for_tx(txn)

    # placeholder, single output that isn't change
    pout = BasicPSBTOutput(idx=0)
    psbt.outputs.append(pout)

    print("Guestimate fee: %.8f BTC" % (fee / 1E8))

    if txn.txs_out:
        txn.txs_out[0].coin_value -= fee

    # write txn into PSBT
    with BytesIO() as b:
        txn.stream(b)
        psbt.txn = b.getvalue()

    out_psbt.write(psbt.as_bytes())

    print("PSBT to be signed:\n\n\t" + out_psbt.name, end='\n\n')