Esempio 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 = 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
Esempio 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 = 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
Esempio n. 3
0
def parse_tx(tx_class, 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_class.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_class.parse(f)
                tx.parse_unspents(f)
        except Exception:
            pass

    return tx, tx_db
Esempio n. 4
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")
Esempio n. 5
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")
Esempio n. 6
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()
Esempio n. 7
0
def parse_tx(tx_class, 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_class.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_class.parse(f)
                tx.parse_unspents(f)
        except Exception:
            pass

    return tx, tx_db
Esempio n. 8
0
 def spendable_for_row(r, spendable_class):
     return spendable_class(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])
Esempio n. 9
0
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/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 = Block(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
Esempio n. 10
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)
Esempio n. 11
0
 def from_text(cls, text):
     the_tuple = (text.split("/") + [0, 0, 0])[:7]
     tx_hash_hex, tx_out_index_str, script_hex, coin_value, \
         block_index_available, does_seem_spent, block_index_spent = the_tuple
     tx_hash = h2b_rev(tx_hash_hex)
     tx_out_index = int(tx_out_index_str)
     script = h2b(script_hex)
     coin_value = int(coin_value)
     return cls(coin_value, script, tx_hash, tx_out_index, int(block_index_available),
                int(does_seem_spent), int(block_index_spent))
Esempio n. 12
0
 def get_blockheader_with_transaction_hashes(self, block_hash):
     URL = "%s/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 = Block(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
Esempio n. 13
0
 def from_text(cls, text):
     the_tuple = (text.split("/") + [0, 0, 0])[:7]
     tx_hash_hex, tx_out_index_str, script_hex, coin_value, \
         block_index_available, does_seem_spent, block_index_spent = the_tuple
     tx_hash = h2b_rev(tx_hash_hex)
     tx_out_index = int(tx_out_index_str)
     script = h2b(script_hex)
     coin_value = int(coin_value)
     return cls(coin_value, script, tx_hash, tx_out_index,
                int(block_index_available), int(does_seem_spent),
                int(block_index_spent))
Esempio n. 14
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()
Esempio n. 15
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()
Esempio n. 16
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 = BitcoinMainnet.tx.from_hex(tx_hex)
            except Exception:
                print("Cannot parse tx_hex: %s" % tx_hex)
                raise

            spendable_db = {}
            blank_spendable = BitcoinMainnet.tx.Spendable(
                0, b'', b'\0' * 32, 0)
            for prevout in prevouts:
                coin_value = 1000000
                if len(prevout) == 4:
                    coin_value = prevout[3]
                spendable = BitcoinMainnet.tx.Spendable(
                    coin_value=coin_value,
                    script=BitcoinMainnet.script_tools.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)
Esempio n. 17
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()
Esempio n. 18
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
Esempio n. 19
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
Esempio n. 20
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
Esempio n. 21
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
Esempio n. 22
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
Esempio n. 23
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()
Esempio n. 24
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
Esempio n. 25
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 = network.tx.from_hex(tx_hex)
            except Exception:
                print("Cannot parse tx_hex: %s" % tx_hex)
                raise

            spendable_db = {}
            blank_spendable = network.tx.Spendable(0, b'', b'\0' * 32, 0)
            for prevout in prevouts:
                coin_value = 1000000
                if len(prevout) == 4:
                    coin_value = prevout[3]
                spendable = network.tx.Spendable(
                    coin_value=coin_value, script=network.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)
Esempio n. 26
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
Esempio n. 27
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
Esempio n. 28
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()
Esempio n. 29
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')
Esempio n. 30
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()
Esempio n. 31
0
 def get_blockchain_tip(self):
     URL = "%s/status?q=getLastBlockHash" % self.base_url
     d = urlopen(URL).read().decode("utf8")
     r = json.loads(d)
     return h2b_rev(r.get("lastblockhash"))
Esempio n. 32
0
    def test_issue_39(self):
        """
        See https://github.com/richardkiss/pycoin/issues/39 and
        https://github.com/richardkiss/pycoin/pull/40

        There was a problem validating the following transactions:

        315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f
        dbf38261224ebff0c455c405e2435cfc69adb6b8a42d7b10674d9a4eb0464dca
        de744408e4198c0a39310c8106d1830206e8d8a5392bcf715c9b5ec97d784edd

        This codes tests this.
        """
        TX_B64_LIST = [
            # some encoded transactions (the three listed above and the three
            # that they depend upon)
            ("AQAAAALcOOk1m9faO1g4YgThhtlAhoX0J/XlE2ZttzWqimshaQAAAABqRzBE"
             "AiBdj+6zEkeORo0LUU5j4ROVjXIU+lcqzYcHmn8MwCb8XAIgD6duoFvyQ69t"
             "D5F38kHK9gbQH8/V5i1r77yiTlaeXCcDIQIQChqcosGJMtZXfFjyJVgBhNDg"
             "gibUGVmHSslj48Gy/v/////cOOk1m9faO1g4YgThhtlAhoX0J/XlE2ZttzWq"
             "imshaQEAAABrSDBFAiAIft44cp5tNeT1FVBQGOZZIiAxJztzZpIPOT7jqxe8"
             "HgIhAMpDFkt1fRptEjXxMgDUtfdt2P2k7J/ChUay31sSEejfAyECdZg5E+YA"
             "k7dn6FWXypOX+y9Bjlf5mNavu8U2EWCFscv/////AUCJlQAAAAAAGXapFPzJ"
             "s204z1XX1bTuTd22ssF2EvSMiKwAAAAA"),
            ("AQAAAAEtUf3HWib/PGE4Ag4am7QPH6tuOc6W/q4yGMmuA14AqwEAAABrSDBF"
             "AiEA5PGlIZB+UPxE0zEy7pjJcVpk350sKGDj4EdMUhq4U34CIDCvjTUGpTUu"
             "KwVkRazYVaQtNycOlKYpp7KLIYcOxtdhASEDgIxJPwYZkNK+AB5A8EiuiHAy"
             "C3SJXOLZZS88HHPNbyz/////AvCHSwAAAAAAGXapFPzJs204z1XX1bTuTd22"
             "ssF2EvSMiKzwh0sAAAAAABl2qRQzzvYXSdEboq3wkaXgRWeBd/46bYisAAAA"
             "AA=="),
            ("AQAAAAJa+fLO2OCiRk98qhSvobvRyPsY3qrl0QEZa1jcIn70rgAAAABqRzBE"
             "AiANKFITbLHEu93eBOx29YHRsyockZFIyF+8D9BWXTWK8wIgNvKqF87Ind6w"
             "A3aigYv3KMRHmSgLnyBExWkad7Dc2WwDIQIQChqcosGJMtZXfFjyJVgBhNDg"
             "gibUGVmHSslj48Gy/v////9a+fLO2OCiRk98qhSvobvRyPsY3qrl0QEZa1jc"
             "In70rgEAAABrSDBFAiEA9APIYMTjztPlIyyzWCXnk3It+vCsLwGWGpN4K0kG"
             "qWMCIGLdifJz5mvPrW8FqLDNJrp7Bma+/Qw9pF2feVcX2lBKAyECdZg5E+YA"
             "k7dn6FWXypOX+y9Bjlf5mNavu8U2EWCFscv/////AaAClAAAAAAAGXapFOUK"
             "XY2jOZUbBAutBFPXxAz9dNPciKwAAAAA"),
            ("AQAAAAGfYeIRrb5mi2ycUPFoaEqbONlRKDXMKYFmaW3C1MdaMQAAAABsSTBG"
             "AiEAhIisrGQ/6Sa7DAJtv+pa9nMiHuBTLNAkxlyzDjYvGEQCIQCFH27K+zjJ"
             "ItZHnrCORpOhrBnHvPnUX8mqXy1pGB/4ngEhAhAKGpyiwYky1ld8WPIlWAGE"
             "0OCCJtQZWYdKyWPjwbL+/////wKgxEoAAAAAABl2qRT8ybNtOM9V19W07k3d"
             "trLBdhL0jIisoMRKAAAAAAAZdqkUM872F0nRG6Kt8JGl4EVngXf+Om2IrAAA"
             "AAA="),
            ("AQAAAALCBkSoNGHOnUgtcCy8I87ODdMmW1WL56GNNOIWvaccAAAAAABrSDBF"
             "AiAxKffbGKLs4sDhPFwLZvQlHX+Q20uxr0hFzQqtnSQZQAIhAImY0R1z7HrT"
             "Tt4hR0R/3n3eS8LXk14G94/O8Pc7LDlmAyECE2UQ39BTBuo0mCvz395yuOSd"
             "QyqYBb9kUtOZTnkvnRn/////yRF9O6xy+bn8PWf3KNM1uywKHCYWOL0bgEe1"
             "Zd1jGaIAAAAAakcwRAIgRQ7h/BpT6uurhfpEmEE/Xx5OAZdUohj+Euzr3Zg8"
             "mbkCIDxIakZ02TMLAtt5OHKyy0VQw7uywxjyis6540zeNZdJAyED78tvrsro"
             "6386Jta3YJd/I64guTuYS8oof9K4PDGZeHD/////AeD9HAAAAAAAGXapFB0x"
             "6lo758/yr1vtc3EOtvXV9n1wiKwAAAAA"),
            ("AQAAAAKerCh2TFeXmFaXU1qdQUucoCL5WRFVNZdvNt1FZgp5XQAAAACMSTBG"
             "AiEAvLz97Qz/zSlKSDrllLRwj73G2B7RfaiR1ZspOG5Ae3kCIQD5ATZgiNvH"
             "X8Tn8Ib8RohgW0HGbPRi00XUcvxCTmybGgFBBCsXId9LDBz91gENMCmVXxRE"
             "ZI+E6QOSkToVTtny7tiOJhmHy/jci4KzQmucvUBotsK5r4CiwjhjOkAAXRD6"
             "SWD/////6864dM1/4fxjvltUc0HJ1da9agsSw4LV3KYhGR7FJ+MBAAAAi0gw"
             "RQIhAJIopjUy7dPOHa+LGTvgM4jfZ8pA522/Jx3+uFC4Lz5IAiBzLNoxejaa"
             "dw1CXwOUuzI4rMl0xsuYC5XQaxZNT2TFzwFBBBPpriULEjb9VdVoC8v3E4is"
             "RMmfQByPCJYadSwK/ZZg9TTFGyDXUwW+dQ9tScDzhMWfdLK9DyV4iAbnYh/S"
             "2cr/////A0BCDwAAAAAAGXapFFzGycfh13x6rrUPhNJNj2ViE7xbiKwACT0A"
             "AAAAABl2qRQhQVEH8cwnc3//rGPcfvakBANJxIistBcsAAAAAAAZdqkUMQV+"
             "QpfDgBAsCQ+ixaUK5Kgl0kOIrAAAAAA="),
            ("AQAAAAO1CFlm1mEB3fjCtilQEH+6TbR3UzdJyqafj3mab9Mc6gAAAACKRzBE"
             "AiA8rWZ4BB8YYJp3xtx8jAZdrfQ6B0zjYRdgTS7I5LZF7gIgabCjn9iu9L3n"
             "YvKrdXFJJygtbg6V8iMTLrPh8ghdGvwBQQQrFyHfSwwc/dYBDTAplV8URGSP"
             "hOkDkpE6FU7Z8u7YjiYZh8v43IuCs0JrnL1AaLbCua+AosI4YzpAAF0Q+klg"
             "/////8IGRKg0Yc6dSC1wLLwjzs4N0yZbVYvnoY004ha9pxwAAQAAAItIMEUC"
             "IDNZYWLuCV0nJL6CCGgUfQfNoh0oAACd2lMZn+zJdJCDAiEAqZafa18G1K1x"
             "/6yOvj8h1uAGSM8UjSJJ6479li5sos4BQQTswrqYR5m+x0vFTzgGrrM2k+Gx"
             "gX+hDBAvN8Kq9RRuWdqC4jVNGhGdFD63Ev1TQYXMqvp6b9ztbAZ3ED8i6sFo"
             "/////0Vf19DzvUs2DvFwlVW9viTF+YlXCNYNMD6yUXK9I9RBAgAAAItIMEUC"
             "IQCKbaQY2eH1fsXZFksstrP4B+uxPBwGRe2Wxl7rW5sYGwIgVvVEPdnJNvVj"
             "rh0XZdhqnOAA0Sw39Upqkejrm+yXWnwBQQQ1hDJBuzoTc1ZJ8zyVQjEfRcjW"
             "o8rq3lE+3x3rYZ3Q/9xBEBtsnkFAzps/N8n6C5cK2QAmRGxeGFmbYaGFT5RP"
             "/////wNAQg8AAAAAABl2qRSU70Qwi2d2bI+nKnCP19XGsbSnWoisVEkwAAAA"
             "AAAZdqkUgroT7ai54LzKPXVnWJsPoV6lJ0yIrHjrFQAAAAAAGXapFEFyZV9I"
             "izJXnWmTivO2n9OKDWCdiKwAAAAA"),
            ("AQAAAAHBHumhtHyFj2ma501AFchO/RrrfkY1sYTKsJiYe6i5pAEAAADaAEcw"
             "RAIgJQsMj5xe4yyGSQOseNBu7zuQNbdwYRpmu4tyOeVrDhoCIHTRJ5lHr5OH"
             "JsmDYl4nTEMhT2TeEN8tMNtrt/rFLMaHAUgwRQIhAObKZ2o5NubR2aoXKP7q"
             "oNMI3sv4u33Hnxcu1NBCilhoAiAH5OaEGAC5snVQDIWgXXVWICosFmTHHjXg"
             "y5fNwAO5gAFHUiECzr9qtYCUjRRrfMdx2OZGl0NJ09exHz4DKH0Jl6R307kh"
             "A3umUUhbeiyyIhketkpVkm5iu6v+m17SqUiKrVR7IEKCUq7/////An1KDwAA"
             "AAAAGXapFNxnIa33YyARGtMFwzhMdn1LmeGViKxllyYPAAAAABepFNsSg3N8"
             "2T68HrEpjWRKeEbFWm2WhwAAAAA="),
            ("AQAAAAHZI2Rm7Gvz7UMEKi20P7AIT5AOxlhwW29S0uFz9EPz1QEAAADaAEgw"
             "RQIhAIX1NZuYzrKUHFAxUNYI6yWMUuzCEapuZOUY6TdCspWaAiAchzgPP6if"
             "WNh0cmVkyW1UpygM/eVa1XrtHepCMhvArAFHMEQCIGLJtKtbyJEaH6iQS+hK"
             "xUlGrWwmqdJScz/JfSZ1Qln6AiBNRC+gswEEMjTNR5uVetqCGJkNL2m6fDfk"
             "DyICU/otoQFHUiECzr9qtYCUjRRrfMdx2OZGl0NJ09exHz4DKH0Jl6R307kh"
             "A3umUUhbeiyyIhketkpVkm5iu6v+m17SqUiKrVR7IEKCUq7/////Aux5CAAA"
             "AAAAGXapFDIKbLrYWAn/2ZTB7ToisbIaZ5DoiKzL5TUPAAAAABepFNsSg3N8"
             "2T68HrEpjWRKeEbFWm2WhwAAAAA="),
            (  # 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba
                "AQAAAAGsp/O0VlTCMOCIalf7mIwwRO9ej385cm0wXGHV6BiQPAAAAAD9XQEAS"
                "DBFAiABh6+Sjp0VXEsaycHJEYFTI5q6dndPd118H5w+EG/zPAIhAIgisPZY7e"
                "wiJ00LauneEOvy2gaxu9qrpOUOsHjznj14AUcwRAIgeV8PT1lBp3rgMuy54zd"
                "TeI1+tcsMeNgFV11rAKHZv+0CID4fStkzLRQWrgHicDjpRbydtZxzJyijg6bx"
                "7S+5naekAUzJUkEEkbuiUQkSpb032h+1sWcwEOQ9LG2BLFFOkb+p8usSnhwYM"
                "ynbVb2GjiCarC+8Assz2Y/nS/I/DCNdYSax2DNPhkEEhlxAKTpoDLnAIOex4Q"
                "bYwZFtPO+ZqkMaVtJT5pJW2sCe8SKxqYaBiny2JFMvBiwdH4ciCEhhxcMpHM/"
                "+9OxodEEEjSRV0kA+CHCPwfVWAC8bbNg/mS0IUJf5l0qwiiiDjweJb7qwjzlJ"
                "XhX6b61u2/sedU41+hx4RMQfMioYY9RiE1Ou/////wFAQg8AAAAAABl2qRSuV"
                "rTbE1VNMhxALbOWEYeu0bvtW4isAAAAAA=="),
            (  # 3c9018e8d5615c306d72397f8f5eef44308c98fb576a88e030c25456b4f3a7ac
                # input of
                # 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba
                "AQAAAAGJYyhI+ZcikVcnxcddqNstvxlDQqBCmCj2b/iPqyr31gAAAACLSDBFA"
                "iEAq7yKc/4gVEgL2j8ygdotDFHihBORq9TAn0+QiiA0wY0CIFvJ5NaOr7kY8+"
                "lmIzhkekQZwN4aZQq4mD8dIW4qMdjjAUEEb1XXre/2ARx+rClP5UDFeDC+gOk"
                "1XIOGnJJgpLi/R2ema6y9cLgE3GPVvusUGAKSrX87CDNysdAtejfdl/9cnv//"
                "//8BQEIPAAAAAAAXqRT4FbA22bu85enyoAq9G/PckelVEIcAAAAA")
        ]

        TX_LIST = [
            Tx.from_hex(b2h(binascii.a2b_base64(b64.encode("utf8"))))
            for b64 in TX_B64_LIST
        ]
        TX_DB = dict((tx.hash(), tx) for tx in TX_LIST)
        for h in [
                "315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f",
                "dbf38261224ebff0c455c405e2435cfc69adb6b8a42d7b10674d9a4eb0464dca",
                "de744408e4198c0a39310c8106d1830206e8d8a5392bcf715c9b5ec97d784edd",
                "485716e53b422aca0fe5b1ded21360695ce5f49255d80e10db56458ed6962ff3",
                "837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba"
        ]:
            tx = TX_DB.get(h2b_rev(h))
            self.assertNotEqual(tx, None)
            tx.unspents_from_db(TX_DB)
            for idx, tx_in in enumerate(tx.txs_in):
                self.assertTrue(tx.is_solution_ok(tx_in_idx=idx))
Esempio n. 33
0
 def from_dict(cls, d):
     return cls(d["coin_value"], h2b(d["script_hex"]),
                h2b_rev(d["tx_hash_hex"]), d["tx_out_index"],
                d.get("block_index_available", 0),
                d.get("does_seem_spent", 0), d.get("block_index_spent", 0))
Esempio n. 34
0
    def test_issue_39(self):
        """
        See https://github.com/richardkiss/pycoin/issues/39 and
        https://github.com/richardkiss/pycoin/pull/40

        There was a problem validating the following transactions:

        315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f
        dbf38261224ebff0c455c405e2435cfc69adb6b8a42d7b10674d9a4eb0464dca
        de744408e4198c0a39310c8106d1830206e8d8a5392bcf715c9b5ec97d784edd

        This codes tests this.
        """
        TX_B64_LIST = [
            # some encoded transactions (the three listed above and the three
            # that they depend upon)
            (
                "AQAAAALcOOk1m9faO1g4YgThhtlAhoX0J/XlE2ZttzWqimshaQAAAABqRzBE"
                "AiBdj+6zEkeORo0LUU5j4ROVjXIU+lcqzYcHmn8MwCb8XAIgD6duoFvyQ69t"
                "D5F38kHK9gbQH8/V5i1r77yiTlaeXCcDIQIQChqcosGJMtZXfFjyJVgBhNDg"
                "gibUGVmHSslj48Gy/v/////cOOk1m9faO1g4YgThhtlAhoX0J/XlE2ZttzWq"
                "imshaQEAAABrSDBFAiAIft44cp5tNeT1FVBQGOZZIiAxJztzZpIPOT7jqxe8"
                "HgIhAMpDFkt1fRptEjXxMgDUtfdt2P2k7J/ChUay31sSEejfAyECdZg5E+YA"
                "k7dn6FWXypOX+y9Bjlf5mNavu8U2EWCFscv/////AUCJlQAAAAAAGXapFPzJ"
                "s204z1XX1bTuTd22ssF2EvSMiKwAAAAA"
            ),
            (
                "AQAAAAEtUf3HWib/PGE4Ag4am7QPH6tuOc6W/q4yGMmuA14AqwEAAABrSDBF"
                "AiEA5PGlIZB+UPxE0zEy7pjJcVpk350sKGDj4EdMUhq4U34CIDCvjTUGpTUu"
                "KwVkRazYVaQtNycOlKYpp7KLIYcOxtdhASEDgIxJPwYZkNK+AB5A8EiuiHAy"
                "C3SJXOLZZS88HHPNbyz/////AvCHSwAAAAAAGXapFPzJs204z1XX1bTuTd22"
                "ssF2EvSMiKzwh0sAAAAAABl2qRQzzvYXSdEboq3wkaXgRWeBd/46bYisAAAA"
                "AA=="
            ),
            (
                "AQAAAAJa+fLO2OCiRk98qhSvobvRyPsY3qrl0QEZa1jcIn70rgAAAABqRzBE"
                "AiANKFITbLHEu93eBOx29YHRsyockZFIyF+8D9BWXTWK8wIgNvKqF87Ind6w"
                "A3aigYv3KMRHmSgLnyBExWkad7Dc2WwDIQIQChqcosGJMtZXfFjyJVgBhNDg"
                "gibUGVmHSslj48Gy/v////9a+fLO2OCiRk98qhSvobvRyPsY3qrl0QEZa1jc"
                "In70rgEAAABrSDBFAiEA9APIYMTjztPlIyyzWCXnk3It+vCsLwGWGpN4K0kG"
                "qWMCIGLdifJz5mvPrW8FqLDNJrp7Bma+/Qw9pF2feVcX2lBKAyECdZg5E+YA"
                "k7dn6FWXypOX+y9Bjlf5mNavu8U2EWCFscv/////AaAClAAAAAAAGXapFOUK"
                "XY2jOZUbBAutBFPXxAz9dNPciKwAAAAA"
            ),
            (
                "AQAAAAGfYeIRrb5mi2ycUPFoaEqbONlRKDXMKYFmaW3C1MdaMQAAAABsSTBG"
                "AiEAhIisrGQ/6Sa7DAJtv+pa9nMiHuBTLNAkxlyzDjYvGEQCIQCFH27K+zjJ"
                "ItZHnrCORpOhrBnHvPnUX8mqXy1pGB/4ngEhAhAKGpyiwYky1ld8WPIlWAGE"
                "0OCCJtQZWYdKyWPjwbL+/////wKgxEoAAAAAABl2qRT8ybNtOM9V19W07k3d"
                "trLBdhL0jIisoMRKAAAAAAAZdqkUM872F0nRG6Kt8JGl4EVngXf+Om2IrAAA"
                "AAA="
            ),
            (
                "AQAAAALCBkSoNGHOnUgtcCy8I87ODdMmW1WL56GNNOIWvaccAAAAAABrSDBF"
                "AiAxKffbGKLs4sDhPFwLZvQlHX+Q20uxr0hFzQqtnSQZQAIhAImY0R1z7HrT"
                "Tt4hR0R/3n3eS8LXk14G94/O8Pc7LDlmAyECE2UQ39BTBuo0mCvz395yuOSd"
                "QyqYBb9kUtOZTnkvnRn/////yRF9O6xy+bn8PWf3KNM1uywKHCYWOL0bgEe1"
                "Zd1jGaIAAAAAakcwRAIgRQ7h/BpT6uurhfpEmEE/Xx5OAZdUohj+Euzr3Zg8"
                "mbkCIDxIakZ02TMLAtt5OHKyy0VQw7uywxjyis6540zeNZdJAyED78tvrsro"
                "6386Jta3YJd/I64guTuYS8oof9K4PDGZeHD/////AeD9HAAAAAAAGXapFB0x"
                "6lo758/yr1vtc3EOtvXV9n1wiKwAAAAA"
            ),
            (
                "AQAAAAKerCh2TFeXmFaXU1qdQUucoCL5WRFVNZdvNt1FZgp5XQAAAACMSTBG"
                "AiEAvLz97Qz/zSlKSDrllLRwj73G2B7RfaiR1ZspOG5Ae3kCIQD5ATZgiNvH"
                "X8Tn8Ib8RohgW0HGbPRi00XUcvxCTmybGgFBBCsXId9LDBz91gENMCmVXxRE"
                "ZI+E6QOSkToVTtny7tiOJhmHy/jci4KzQmucvUBotsK5r4CiwjhjOkAAXRD6"
                "SWD/////6864dM1/4fxjvltUc0HJ1da9agsSw4LV3KYhGR7FJ+MBAAAAi0gw"
                "RQIhAJIopjUy7dPOHa+LGTvgM4jfZ8pA522/Jx3+uFC4Lz5IAiBzLNoxejaa"
                "dw1CXwOUuzI4rMl0xsuYC5XQaxZNT2TFzwFBBBPpriULEjb9VdVoC8v3E4is"
                "RMmfQByPCJYadSwK/ZZg9TTFGyDXUwW+dQ9tScDzhMWfdLK9DyV4iAbnYh/S"
                "2cr/////A0BCDwAAAAAAGXapFFzGycfh13x6rrUPhNJNj2ViE7xbiKwACT0A"
                "AAAAABl2qRQhQVEH8cwnc3//rGPcfvakBANJxIistBcsAAAAAAAZdqkUMQV+"
                "QpfDgBAsCQ+ixaUK5Kgl0kOIrAAAAAA="
            ),
            (
                "AQAAAAO1CFlm1mEB3fjCtilQEH+6TbR3UzdJyqafj3mab9Mc6gAAAACKRzBE"
                "AiA8rWZ4BB8YYJp3xtx8jAZdrfQ6B0zjYRdgTS7I5LZF7gIgabCjn9iu9L3n"
                "YvKrdXFJJygtbg6V8iMTLrPh8ghdGvwBQQQrFyHfSwwc/dYBDTAplV8URGSP"
                "hOkDkpE6FU7Z8u7YjiYZh8v43IuCs0JrnL1AaLbCua+AosI4YzpAAF0Q+klg"
                "/////8IGRKg0Yc6dSC1wLLwjzs4N0yZbVYvnoY004ha9pxwAAQAAAItIMEUC"
                "IDNZYWLuCV0nJL6CCGgUfQfNoh0oAACd2lMZn+zJdJCDAiEAqZafa18G1K1x"
                "/6yOvj8h1uAGSM8UjSJJ6479li5sos4BQQTswrqYR5m+x0vFTzgGrrM2k+Gx"
                "gX+hDBAvN8Kq9RRuWdqC4jVNGhGdFD63Ev1TQYXMqvp6b9ztbAZ3ED8i6sFo"
                "/////0Vf19DzvUs2DvFwlVW9viTF+YlXCNYNMD6yUXK9I9RBAgAAAItIMEUC"
                "IQCKbaQY2eH1fsXZFksstrP4B+uxPBwGRe2Wxl7rW5sYGwIgVvVEPdnJNvVj"
                "rh0XZdhqnOAA0Sw39Upqkejrm+yXWnwBQQQ1hDJBuzoTc1ZJ8zyVQjEfRcjW"
                "o8rq3lE+3x3rYZ3Q/9xBEBtsnkFAzps/N8n6C5cK2QAmRGxeGFmbYaGFT5RP"
                "/////wNAQg8AAAAAABl2qRSU70Qwi2d2bI+nKnCP19XGsbSnWoisVEkwAAAA"
                "AAAZdqkUgroT7ai54LzKPXVnWJsPoV6lJ0yIrHjrFQAAAAAAGXapFEFyZV9I"
                "izJXnWmTivO2n9OKDWCdiKwAAAAA"
            ),
            (
                "AQAAAAHBHumhtHyFj2ma501AFchO/RrrfkY1sYTKsJiYe6i5pAEAAADaAEcw"
                "RAIgJQsMj5xe4yyGSQOseNBu7zuQNbdwYRpmu4tyOeVrDhoCIHTRJ5lHr5OH"
                "JsmDYl4nTEMhT2TeEN8tMNtrt/rFLMaHAUgwRQIhAObKZ2o5NubR2aoXKP7q"
                "oNMI3sv4u33Hnxcu1NBCilhoAiAH5OaEGAC5snVQDIWgXXVWICosFmTHHjXg"
                "y5fNwAO5gAFHUiECzr9qtYCUjRRrfMdx2OZGl0NJ09exHz4DKH0Jl6R307kh"
                "A3umUUhbeiyyIhketkpVkm5iu6v+m17SqUiKrVR7IEKCUq7/////An1KDwAA"
                "AAAAGXapFNxnIa33YyARGtMFwzhMdn1LmeGViKxllyYPAAAAABepFNsSg3N8"
                "2T68HrEpjWRKeEbFWm2WhwAAAAA="
            ),
            (
                "AQAAAAHZI2Rm7Gvz7UMEKi20P7AIT5AOxlhwW29S0uFz9EPz1QEAAADaAEgw"
                "RQIhAIX1NZuYzrKUHFAxUNYI6yWMUuzCEapuZOUY6TdCspWaAiAchzgPP6if"
                "WNh0cmVkyW1UpygM/eVa1XrtHepCMhvArAFHMEQCIGLJtKtbyJEaH6iQS+hK"
                "xUlGrWwmqdJScz/JfSZ1Qln6AiBNRC+gswEEMjTNR5uVetqCGJkNL2m6fDfk"
                "DyICU/otoQFHUiECzr9qtYCUjRRrfMdx2OZGl0NJ09exHz4DKH0Jl6R307kh"
                "A3umUUhbeiyyIhketkpVkm5iu6v+m17SqUiKrVR7IEKCUq7/////Aux5CAAA"
                "AAAAGXapFDIKbLrYWAn/2ZTB7ToisbIaZ5DoiKzL5TUPAAAAABepFNsSg3N8"
                "2T68HrEpjWRKeEbFWm2WhwAAAAA="
            ),
            (  # 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba
                "AQAAAAGsp/O0VlTCMOCIalf7mIwwRO9ej385cm0wXGHV6BiQPAAAAAD9XQEAS"
                "DBFAiABh6+Sjp0VXEsaycHJEYFTI5q6dndPd118H5w+EG/zPAIhAIgisPZY7e"
                "wiJ00LauneEOvy2gaxu9qrpOUOsHjznj14AUcwRAIgeV8PT1lBp3rgMuy54zd"
                "TeI1+tcsMeNgFV11rAKHZv+0CID4fStkzLRQWrgHicDjpRbydtZxzJyijg6bx"
                "7S+5naekAUzJUkEEkbuiUQkSpb032h+1sWcwEOQ9LG2BLFFOkb+p8usSnhwYM"
                "ynbVb2GjiCarC+8Assz2Y/nS/I/DCNdYSax2DNPhkEEhlxAKTpoDLnAIOex4Q"
                "bYwZFtPO+ZqkMaVtJT5pJW2sCe8SKxqYaBiny2JFMvBiwdH4ciCEhhxcMpHM/"
                "+9OxodEEEjSRV0kA+CHCPwfVWAC8bbNg/mS0IUJf5l0qwiiiDjweJb7qwjzlJ"
                "XhX6b61u2/sedU41+hx4RMQfMioYY9RiE1Ou/////wFAQg8AAAAAABl2qRSuV"
                "rTbE1VNMhxALbOWEYeu0bvtW4isAAAAAA=="
            ),
            (  # 3c9018e8d5615c306d72397f8f5eef44308c98fb576a88e030c25456b4f3a7ac
               # input of
               # 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba
                "AQAAAAGJYyhI+ZcikVcnxcddqNstvxlDQqBCmCj2b/iPqyr31gAAAACLSDBFA"
                "iEAq7yKc/4gVEgL2j8ygdotDFHihBORq9TAn0+QiiA0wY0CIFvJ5NaOr7kY8+"
                "lmIzhkekQZwN4aZQq4mD8dIW4qMdjjAUEEb1XXre/2ARx+rClP5UDFeDC+gOk"
                "1XIOGnJJgpLi/R2ema6y9cLgE3GPVvusUGAKSrX87CDNysdAtejfdl/9cnv//"
                "//8BQEIPAAAAAAAXqRT4FbA22bu85enyoAq9G/PckelVEIcAAAAA"
            )
        ]

        TX_LIST = [Tx.from_hex(b2h(binascii.a2b_base64(b64.encode("utf8")))) for b64 in TX_B64_LIST]
        TX_DB = dict((tx.hash(), tx) for tx in TX_LIST)
        for h in ["315ac7d4c26d69668129cc352851d9389b4a6868f1509c6c8b66bead11e2619f",
                  "dbf38261224ebff0c455c405e2435cfc69adb6b8a42d7b10674d9a4eb0464dca",
                  "de744408e4198c0a39310c8106d1830206e8d8a5392bcf715c9b5ec97d784edd",
                  "485716e53b422aca0fe5b1ded21360695ce5f49255d80e10db56458ed6962ff3",
                  "837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba"]:
            tx = TX_DB.get(h2b_rev(h))
            self.assertNotEqual(tx, None)
            tx.unspents_from_db(TX_DB)
            for idx, tx_in in enumerate(tx.txs_in):
                self.assertTrue(tx.is_signature_ok(tx_in_idx=idx))
Esempio n. 35
0
 def get_blockchain_tip(self):
     URL = "%s/status?q=getLastBlockHash" % self.base_url
     d = urlopen(URL).read().decode("utf8")
     r = json.loads(d)
     return h2b_rev(r.get("lastblockhash"))
Esempio n. 36
0
import threading
import unittest

from pycoin.encoding.hexbytes import h2b_rev
from pycoin.services import providers
from pycoin.services.blockchain_info import BlockchainInfoProvider
from pycoin.services.blockcypher import BlockcypherProvider
from pycoin.services.blockexplorer import BlockExplorerProvider
from pycoin.services.chain_so import ChainSoProvider
from pycoin.services.insight import InsightProvider


BLOCK_0_HASH = h2b_rev("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
BLOCK_1_HASH = h2b_rev("00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048")


tx_id_for_net = {
    "BTC": ["b958e4a3ccd5bc8fe0ff6fafd635199313e347b88a8102040c05dd123f32a4f3",
            "d1ef46055a84fd02ee82580d691064780def18614d98646371c3448ca20019ac",
            "69916297f7adde13457b8244e2d704966097e9519ec8fd6f2e7af8c2a60f70f2",
            "c586389e5e4b3acb9d6c8be1c19ae8ab2795397633176f5a6442a261bbdefc3a"],
    "XTN": ["4586e67ee5adcdbc97ed3d2a026ee8703df2ed3553854c186c216e90cd761b69"],
    "DOGE": ["ed7df4e7506ac8447b6983c8ad79da1af86cddda0ff012f7db83e664f61ef6cf"],
    "XDT": ["19dd5c3423e606b5b5dd30b070688bdf9af27fa736e8f3aeb2b68d92a50e67ef"],
}


class ServicesTest(unittest.TestCase):
    def test_env(self):
        CS = "blockchain.info blockexplorer.com chain.so insight:https://hostname/url"
Esempio n. 37
0
 def check_provider_tx_for_tx_hash(self, p, networks):
     for net in networks:
         b = p(net)
         for tx_id in tx_id_for_net[net]:
             tx = b.tx_for_tx_hash(h2b_rev(tx_id))
             self.assertEqual(tx.id(), tx_id)
Esempio n. 38
0
 def from_dict(cls, d):
     return cls(d["coin_value"], h2b(d["script_hex"]),
                h2b_rev(d["tx_hash_hex"]), d["tx_out_index"],
                d.get("block_index_available", 0), d.get("does_seem_spent", 0),
                d.get("block_index_spent", 0))