def test_vsize(self):
        segwit_tx = Transaction(read_test_data("size_segwit.txt"))
        non_segwit_tx = Transaction(read_test_data("size_non_segwit.txt"))

        self.assertEqual(non_segwit_tx.vsize, non_segwit_tx.size)
        self.assertEqual(non_segwit_tx.vsize, 189)

        self.assertNotEqual(segwit_tx.vsize, segwit_tx.size)
        self.assertEqual(segwit_tx.vsize, 208)
        self.assertEqual(segwit_tx.size, 373)
    def test_bip69(self):
        noncompliant = "blockchain_parser/tests/bip69_false.txt"
        with open(os.path.join(os.getcwd(), noncompliant)) as f:
            data = a2b_hex(f.read().strip())

        tx = Transaction(data)
        self.assertFalse(tx.uses_bip69())

        compliant = "blockchain_parser/tests/bip69_true.txt"
        with open(os.path.join(os.getcwd(), compliant)) as f:
            data = a2b_hex(f.read().strip())

        tx = Transaction(data)
        self.assertTrue(tx.uses_bip69())
    def get_transaction(self, txid, db):
        """Yields the transaction contained in the .blk files as a python
         object, similar to
         https://developer.bitcoin.org/reference/rpc/getrawtransaction.html
        """

        byte_arr = bytearray.fromhex(txid)
        byte_arr.reverse()
        tx_hash = hexlify(b't').decode('utf-8') + \
            hexlify(byte_arr).decode('utf-8')

        tx_hash_fmtd = unhexlify(tx_hash)
        raw_hex = db.get(tx_hash_fmtd)

        tx_idx = DBTransactionIndex(utils.format_hash(tx_hash_fmtd), raw_hex)
        blk_file = os.path.join(self.path, "blk%05d.dat" % tx_idx.blockfile_no)
        raw_hex = get_block(blk_file, tx_idx.file_offset)

        offset = tx_idx.block_offset

        transaction_data = raw_hex[80:]
        # Try from 1024 (1KiB) -> 1073741824 (1GiB) slice widths
        for j in range(0, 20):
            try:
                offset_e = offset + (1024 * 2**j)
                transaction = Transaction.from_hex(
                    transaction_data[offset:offset_e])
                return transaction
            except Exception:
                continue

        return None
    def test_segwit(self):
        tx = Transaction(read_test_data("segwit.txt"))
        self.assertTrue(tx.is_segwit)
        id = "22116f1d76ab425ddc6d10d184331e70e080dd6275d7aa90237ceb648dc38224"
        self.assertTrue(tx.txid == id)
        h = "1eac09f372a8c13bb7dea6bd66ee71a6bcc469b57b35c1e394ad7eb7c107c507"
        self.assertTrue(tx.hash == h)

        segwit_input = tx.inputs[0]
        self.assertTrue(len(segwit_input.witnesses) == 4)
        self.assertTrue(len(segwit_input.witnesses[0]) == 0)

        wit_1 = "3045022100bc2ba8808127f8a74beed6dfa1b9fe54675c55aab85a61d7" \
                "a74c15b993e67e5f02204dada4e15f0b4e659dae7bf0d0f648010d1f2b" \
                "665f587a35eb6f22e44194952301"

        wit_2 = "3045022100f4c7ec7c2064fe2cc4389733ac0a57d8080a62180a004b02" \
                "a19b89267113a17f022004ee9fdb081359c549ee42ffb58279363563ea" \
                "f0191cd8b2b0ceebf62146b50b01"

        wit_3 = "5221022b003d276bce58bef509bdcd9cf7e156f0eae18e1175815282e6" \
                "5e7da788bb5b21035c58f2f60ecf38c9c8b9d1316b662627ec672f5fd9" \
                "12b1a2cc28d0b9b00575fd2103c96d495bfdd5ba4145e3e046fee45e84" \
                "a8a48ad05bd8dbb395c011a32cf9f88053ae"

        parsed_1 = b2a_hex(segwit_input.witnesses[1]).decode("utf-8")
        parsed_2 = b2a_hex(segwit_input.witnesses[2]).decode("utf-8")
        parsed_3 = b2a_hex(segwit_input.witnesses[3]).decode("utf-8")

        self.assertEqual(parsed_1, wit_1)
        self.assertEqual(parsed_2, wit_2)
        self.assertEqual(parsed_3, wit_3)
    def test_rbf(self):
        data = a2b_hex("01000000019222bbb054bb9f94571dfe769af5866835f2a97e8839"
                       "59fa757de4064bed8bca01000000035101b1000000000100000000"
                       "00000000016a01000000")
        tx = Transaction(data)
        self.assertTrue(tx.uses_replace_by_fee())

        coinbase = a2b_hex("01000000010000000000000000000000000000000000000000"
                           "000000000000000000000000ffffffff4203c8e405fabe6d6d"
                           "98b0e98e3809941f1fd8cafe7c8236e27b8d1a776b1835aa54"
                           "8bb84fe5b5f3d7010000000000000002650300aaa757eb0000"
                           "002f736c7573682f0000000001baa98396000000001976a914"
                           "7c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac000000"
                           "00")
        tx = Transaction(coinbase)
        self.assertTrue(tx.is_coinbase())
        self.assertFalse(tx.uses_replace_by_fee())
    def test_large(self):
        data = read_test_data("large_tx.txt")

        tx = Transaction(data)
        self.assertTrue(
            tx.hash == "29a3efd3ef04f9153d47a990bd7b048a4b2d213daa"
                       "a5fb8ed670fb85f13bdbcf")
        self.assertTrue(tx.size == len(tx.hex))
    def test_bip69(self):
        non_compliant = read_test_data("bip69_false.txt")
        tx = Transaction(non_compliant)
        self.assertFalse(tx.uses_bip69())

        compliant = read_test_data("bip69_true.txt")
        tx = Transaction(compliant)
        self.assertTrue(tx.uses_bip69())
Exemplo n.º 8
0
    async def handle(self):
        global current_block_count

        msg = await self.zmqSubSocket.recv_multipart()
        topic = msg[0]
        body = msg[1]
        sequence = "Unknown"

        if len(msg[-1]) == 4:
            msgSequence = struct.unpack('<I', msg[-1])[-1]
            sequence = str(msgSequence)

        if topic == b"rawblock":
            try:
                block = Block(body, current_block_count + 1)
                current_block_count += 1

                documents = []
                d_txids = []
                for tx in block.transactions:
                    res = tna.extract(block, tx)
                    #print(json.dumps(res, indent=4))
                    documents.append(res)
                    d_txids.append(tx.hash)

                print("height={} inserted={}".format(
                    block.height,
                    len(db.confirmed.insert_many(documents).inserted_ids)))
                db.meta.update({'column': 'last_block'},
                               {"height": block.height},
                               upsert=True)

                for txid in d_txids:
                    db.unconfirmed.delete_one({'tx': {'h': txid}})
            except AssertionError:
                print('error: rawblock')

        elif topic == b"rawtx":
            try:
                tx = Transaction.from_hex(body)
                res = tna.extract(None, tx)
                db.unconfirmed.insert_one(res)
                print('inserted tx: {}'.format(tx.hash))
            except:
                print('error: rawtx')
        # schedule to receive next message
        asyncio.ensure_future(self.handle())
    def test_rbf(self):
        data = a2b_hex("01000000019222bbb054bb9f94571dfe769af5866835f2a97e8839"
                       "59fa757de4064bed8bca01000000035101b1000000000100000000"
                       "00000000016a01000000")
        tx = Transaction(data)
        self.assertTrue(tx.uses_replace_by_fee())

        coinbase = a2b_hex("01000000010000000000000000000000000000000000000000"
                           "000000000000000000000000ffffffff4203c8e405fabe6d6d"
                           "98b0e98e3809941f1fd8cafe7c8236e27b8d1a776b1835aa54"
                           "8bb84fe5b5f3d7010000000000000002650300aaa757eb0000"
                           "002f736c7573682f0000000001baa98396000000001976a914"
                           "7c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac000000"
                           "00")
        tx = Transaction(coinbase)
        self.assertTrue(tx.is_coinbase())
        self.assertFalse(tx.uses_replace_by_fee())
    def test_bip69(self):
        noncompliant = "bip69_false.txt"
        with open(os.path.join(dir_path, noncompliant)) as f:
            data = a2b_hex(f.read().strip())

        tx = Transaction(data)
        self.assertFalse(tx.uses_bip69())

        compliant = "bip69_true.txt"
        with open(os.path.join(dir_path, compliant)) as f:
            data = a2b_hex(f.read().strip())

        tx = Transaction(data)
        self.assertTrue(tx.uses_bip69())
Exemplo n.º 11
0
                    action="store_true",
                    help="show json from tna")
args = parser.parse_args()

rpc = bitcoin.rpc.RawProxy(btc_conf_file=btc_conf_file)

mongo = pymongo.MongoClient(os.getenv('MONGO_URL'))
db = mongo[os.getenv('MONGO_NAME')]

if not args.dry:
    print('deleted {} txs from unconfirmed'.format(
        db.unconfirmed.delete_many({}).deleted_count))

documents = []
transactions = rpc.getrawmempooltxs()
total_transactions = len(transactions)
for txdata_index, txdata in enumerate(transactions):
    tx = Transaction.from_hex(binascii.unhexlify(txdata))
    res = tna.extract(None, tx)
    if args.verbose:
        print(json.dumps(res, indent=4))
    documents.append(res)

    print("{}%\t{}/{}".format(
        round((txdata_index / total_transactions) * 100, 2), txdata_index,
        total_transactions))

if not args.dry:
    inserted = len(db.unconfirmed.insert_many(documents).inserted_ids)
    print("inserted={}".format(inserted))
Exemplo n.º 12
0
import os
import json
import base64
import argparse
import binascii
from dotenv import load_dotenv
from blockchain_parser.block import Block
from blockchain_parser.transaction import Transaction
import bitcoin.rpc
import tna

load_dotenv()

btc_conf_file = os.path.expanduser(os.getenv("BTC_CONF_FILE"))

parser = argparse.ArgumentParser(description="render a tx with tna")
parser.add_argument("--txid", type=str, required=True, help="txid to look up")
args = parser.parse_args()

rpc = bitcoin.rpc.RawProxy(btc_conf_file=btc_conf_file)

raw_tx_json = rpc.getrawtransaction(args.txid, 1)

raw_block_json = rpc.getblock(raw_tx_json['blockhash'])
raw_block = binascii.unhexlify(rpc.getblock(raw_tx_json['blockhash'], False))
block = Block(raw_block, raw_block_json['height'])

tx = Transaction.from_hex(binascii.unhexlify(raw_tx_json['hex']))
res = tna.extract(block, tx)
print(json.dumps(res, sort_keys=True, indent=4))
 def test_bech32_p2wsh(self):
     tx = Transaction(read_test_data("bech32_p2wsh.txt"))
     self.assertEqual(["3GMKKFPNUg13VktgihUD8QfXVQRBdoDNDf"], [a.address for a in tx.outputs[0].addresses])
     self.assertEqual(["bc1qday7wsftyv4r6qkpn8907s8fy3kexkny0xwrd8d4wlk06zffzyuqpp629n"], [a.address for a in tx.outputs[1].addresses])
 def test_bech32_p2wpkh(self):
     tx = Transaction(read_test_data("bech32_p2wpkh.txt"))
     self.assertEqual(["3BBqfnaPbgi5KWECWdFpvryUfw7QatWy37"], [a.address for a in tx.outputs[0].addresses])
     self.assertEqual(["bc1q4z0874xmfxe3xeqknulgnqhukhfjwh5tvjrr2x"], [a.address for a in tx.outputs[1].addresses])
    def test_unknown_scripts(self):
        data = read_test_data("scripts_invalid.txt")
        tx = Transaction(data)

        for output in tx.outputs:
            self.assertEqual([], output.addresses)
    def test_large(self):
        data = a2b_hex(
            "010000000b04a4abee8360f7a660bcf1c298496d927b6ad1f25dd12485"
            "e6a572e275cbd43f000000008b483045022100c6d59290df934bac08bc"
            "4124b06154ee21394d37ec958d145129a885dbd63eab0220036251120e"
            "4ceacc8e9ff13585049945c7dbdb85921a6e077a80c7e410931f4a0141"
            "04f3ce8948c592690cb36a7e6e31534927569f41e45c77fbdb95fdb0e2"
            "35717a295b2a281c04619139c453dd9139e951086325b4021bd28da6fc"
            "3da86943cd04cfffffffff21fd91e6dd64838eadce9bc0d687af571779"
            "c3af4b53bada845485466decf005000000008b48304502205d309b632a"
            "816f1f2479b8ca284301fce3fc8f979306722bba4cf28c8fa7ed760221"
            "00a3313ee59bbf0e61e29302b2ea597a993a73e93be841f2f7dd3f6e96"
            "23572793014104ca3b25750307a483c0cff8efb1413c98b4e18765485d"
            "94eac147f21f507169997a72aeb50f0b01ed6b468c9554143125f63c0b"
            "2b229a597e695718b86d711607ffffffff4dd6c46e3e68fc05243b6f89"
            "4e2f3e4d2782d1c8a3d17b9a2c5e78912bbaf433010000008b48304502"
            "2100f3f1d6c0e76a00e89a5278fa14eae8de93454174199f72c98aef54"
            "dabb2074d10220172dc0d6958efa8dc18c621f2d56fd0484ecb04e3d65"
            "e2284268916c1c324ade014104daeab6af397baf06fcc91b6c04a28ffb"
            "2cd80312e954a2a55f7c864094608032ef657e8296dfc2f86ecf28fe32"
            "925c0f648d3ef16b96934a34b29dd871ff057affffffff52aabc7fdee0"
            "588d63fff3fc00e20b00a87cffa6a37aad7168741b1f0e77bdff000000"
            "008b4830450220274a5a9577f0786fb17d373b6d1995a6cff752320bf4"
            "e3d5ee41b15fdd86ef2a022100fd1d0c0f43d05e479430c3c9bd5481f5"
            "be929a7f2b82d14292ef192653c3b94c014104988828ea7144ff00def9"
            "988e88aad98b1f22d01000fc4b52d1003c9b32de0534cff71c0a045098"
            "bb28f699bcc9db13533c0998eb2133085d37cac65b5bd74c1fffffffff"
            "5aab5581c575a56a803ef5d8698dc34014261d196ada1da3300731380d"
            "7e672d000000008b48304502201615a116a2e057f3f8f2a63340d0387b"
            "820a6f9d1067758f4f6cdec76c04951a022100a1ada9e03a0d9603743d"
            "41347ffd992642544d6dfdc51121b7bf622e12cb1547014104830b3b13"
            "9b0a8707f348840b0fa358164869fbc0c423a2785cb0a18ff73517f887"
            "8cefd643e86e682eb93d07216f76993c9e980592de07c507c3a2659eff"
            "f6aaffffffff74d7cd370a334aabee3b8328b67a63f1768583405e73eb"
            "d291dd86189983a61c000000008a4730440220432ff0f90a3f5372a8dc"
            "4b3d2e7165e110efa16b40784ea4d5ab866b736712ed02201a759b630d"
            "562f4dbc4a7d2fca406ad54e235564346bc360dec26d6e72bb60fa0141"
            "04ca0bb72303672885ad953279309694c71574d50d2c6e1f5f1e7ab1b0"
            "bf3df67e5439b3f6e2501dda539812e414991ebaa547631374ce2bda9d"
            "d7211099886827ffffffff8941eb7fe688ff48357981c4756906e331c0"
            "7f332429be5b2cfc7a945644f80f000000008a47304402204e074678b5"
            "25927a8f459d1dc93ad738ce02c0ea77c50a749647032eda662eee0220"
            "3c1a98e9b116dc2fe9e7325a5696ad8e3ad26d2d10503e6e3209f4f5f4"
            "0f6e34014104f9baa86b46b04f2a2dc4270903bcca9444026b7f184d87"
            "9f089462e332f260f6de8e05f08285a4a3c716220d9ec0f7e9fde354c7"
            "79f32f00dd4d4cd8d4a1ac28ffffffff948be2e03f9537a35319e8cee2"
            "b7b9ed2769ca59734e5d4b42951ef7ba3bb4a8000000008b4830450221"
            "00fcf1deaaa047e8f1b8b8ac783760ea5a0af15adbb9eed1c1748942a5"
            "7510e27402204c278b12c4991480dc714af66395f5d8f42e411423bf27"
            "b024f62267c45a0d37014104cfd128c3f322b59c21d452d5c4c7b4d1a3"
            "237a2d31c6f4033b32db78c19cb342ffc151acc272a02a13ba985a523b"
            "655689d8118f502b8a7fb8df5fc7bd8458ceffffffffb2cae04cf238b4"
            "d47c614da5ce9948f089a02f1ff3e22cda6b9f9196bda8721501000000"
            "8b483045022017a74373ef19756e275f2d987925a8bd22cfaf1c93eede"
            "7db63102dc73b7cfd0022100fd2f040d7d3ccd1a2188923f8c7560253a"
            "a2a910d8e9cd06a8a05fc69c12f6ce014104daeab6af397baf06fcc91b"
            "6c04a28ffb2cd80312e954a2a55f7c864094608032ef657e8296dfc2f8"
            "6ecf28fe32925c0f648d3ef16b96934a34b29dd871ff057affffffffbe"
            "75c9f1faf79fb885018e3353ada4a7fb5c989bc26f031c5aee69d1eaba"
            "d957000000008a4730440220360d35b0a98dd086d242f8976aa704b808"
            "541ad78ef5cba45e4eb73c1efbaaa7022025a3d981b9e0836a2493698b"
            "802bf7f0eae72de0252c7eac059ad14b1b27001b014104d969f0d45619"
            "6f4c16945bc71fc460615002d1554fc8d774288aa8fc5c9eca1622a3dc"
            "b1e6a8314c94844e516c0543316b2e75d465c8fc2f0d0d20334e53f7db"
            "ffffffffbcbad95cac8bbe08538f7b12c240e96866358dfa819de6e940"
            "bb60ce7fae5c3d000000008b483045022100d916990888d0d26246b8d6"
            "cb944b1e8ebd6a4cdb2965ff7e4430883eef02c4e102205693b96aa1d6"
            "e9335f3cb2986b7f3a03357959e989570d03a56ccdb18a8d7e6d014104"
            "0840a410ed7afdc3e3fe3923ae388413bbd8a9089062403e0adce62212"
            "bccfe1f80400530121cfdba5b52f3e16397f1959b14a09089778afd5ff"
            "41f8a856980fffffffff02005039278c0400001976a914f1c87a5e8ff7"
            "d14e74b858089bf771c94b1b6db488ac00203d88792d00001976a914dc"
            "df2f9892bfa1cb086530354eab3ba078a2f09088ac00000000")

        tx = Transaction(data)
        self.assertTrue(tx.hash == "29a3efd3ef04f9153d47a990bd7b048a4b2d213daa"
                        "a5fb8ed670fb85f13bdbcf")
        self.assertTrue(tx.size == len(tx.hex))