Exemplo 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
Exemplo n.º 2
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
Exemplo n.º 3
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")
Exemplo n.º 4
0
 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])
Exemplo n.º 5
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
Exemplo n.º 6
0
 def spendables_for_address(self, bitcoin_address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "%s/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
Exemplo n.º 7
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)
Exemplo n.º 8
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
Exemplo n.º 9
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(
                Spendable(coin_value, script, previous_hash, previous_index))

        return spendables
Exemplo n.º 10
0
    def test_issue_39(self):
        """
        See https://github.com/richardkiss/pycoin_grs/issues/39 and
        https://github.com/richardkiss/pycoin_grs/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))
Exemplo n.º 11
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"))
Exemplo n.º 12
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)
Exemplo n.º 13
0
import threading
import unittest

from pycoin_grs.serialize import h2b_rev
from pycoin_grs.services import providers
from pycoin_grs.services.blockchain_info import BlockchainInfoProvider
from pycoin_grs.services.blockcypher import BlockcypherProvider
from pycoin_grs.services.blockexplorer import BlockExplorerProvider
from pycoin_grs.services.chain_so import ChainSoProvider
from pycoin_grs.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"