Пример #1
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()
Пример #2
0
 def _input_tx_to_spendable(self, tx: InputTransaction) -> Spendable:
     outs = tx.output.split(":")
     tx_hash = h2b_rev(outs[0])
     output_n = int(outs[1])
     return Spendable(coin_value=tx.value,
                      script=self._network.ui.script_for_address(
                          tx.address),
                      tx_hash=tx_hash,
                      tx_out_index=output_n)
Пример #3
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()
Пример #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()
Пример #5
0
    def get_spendables_for_address(self, address) -> List[Spendable]:
        """
        Return a list of Spendable objects for the
        given bitcoin address. It needs to create transaction via pycoin library.
        """
        spendables = []
        r = self._request(f"{self._endpoint}get_tx_unspent/{self._network}/{address}")

        print(f"spendables_for_address: {r}")
        for u in r["data"]['txs']:
            coin_value = self._decimals_to_int(u['value'])
            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
Пример #6
0
    def get_spendables_for_address(self, address) -> List[Spendable]:
        """
        Return a list of Spendable objects for the
        given bitcoin address. It needs to create transaction via pycoin library.
        """
        unspent = self.get_unspent_tx(address)
        spendables = []
        r = self._request(f"{self._endpoint}address/{address}/unspent")

        print(f"spendables_for_address: {r}")

        for utx in unspent:
            coin_value = utx["value"]
            script = self._network.ui.script_for_address(address)
            previous_hash = h2b_rev(utx["tx_hash"])
            previous_index = utx["tx_output_n"]
            spendables.append(
                Spendable(coin_value, script, previous_hash, previous_index))
        return spendables
Пример #7
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()
Пример #8
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()