def test_mock_protocol_changes(cp_server):
    assert util.enabled('multisig_addresses') == True

    with util_test.MockProtocolChangesContext(multisig_addresses=False):
        assert util.enabled('multisig_addresses') == False

        with util_test.MockProtocolChangesContext(multisig_addresses=None):
            assert util.enabled('multisig_addresses') == None

        assert util.enabled('multisig_addresses') == False

    assert util.enabled('multisig_addresses') == True
def test_p2sh_encoding_p2sh_source_not_supported(server_db):
    source = P2SH_ADDR[0]
    destination = ADDR[1]

    with util_test.ConfigContext(
            OLD_STYLE_API=True), util_test.MockProtocolChangesContext(
                enhanced_sends=True, p2sh_encoding=True):
        fee = 20000
        fee_per_kb = 50000

        with pytest.raises(exceptions.TransactionError):
            result = api.compose_transaction(server_db,
                                             'send', {
                                                 'source': source,
                                                 'destination': destination,
                                                 'asset': 'XCP',
                                                 'quantity': 100
                                             },
                                             encoding='p2sh',
                                             fee_per_kb=fee_per_kb,
                                             fee=fee)
def test_p2sh_encoding_composed(server_db):
    source = ADDR[0]
    destination = ADDR[1]

    with util_test.ConfigContext(
            DISABLE_ARC4_MOCKING=True,
            OLD_STYLE_API=True), util_test.MockProtocolChangesContext(
                enhanced_sends=True, p2sh_encoding=True):
        # BTC Mainnet tx d90dc8637fd2ab9ae39b7c2929c793c5d28d7dea672afb02fb4001637085e9a1
        datatxhex = "010000000102d2b137e49e930ef3e436b342713d8d07bd378e773c915a5938993d81dc7e6000000000fdab0147304402207848293e88563750f647e949cb594cdbec0beb4070faac73040d77d479420f8302201e0ac32788e98bd984279102b7382576d7ddb4b125d1d507725cbd12d97a2908014d60014d1401434e5452505254590300010042276049e5518791be2ffe2c301f5dfe9ef85dd0400001720034b0410000000000000001500000006a79811e000000000000000054000079cec1665f4800000000000000050000000ca91f2d660000000000000005402736c8de6e34d54000000000000001500c5e4c71e081ceb00000000000000054000000045dc03ec4000000000000000500004af1271cf5fc00000000000000054001e71f8464432780000000000000015000002e1e4191f0d0000000000000005400012bc4aaac2a54000000000000001500079c7e774e411c00000000000000054000000045dc0a6f00000000000000015000002e1e486f661000000000000000540001c807abe13908000000000000000475410426156245525daa71f2e84a40797bcf28099a2c508662a8a33324a703597b9aa2661a79a82ffb4caaa9b15f4094622fbfa85f8b9dc7381f991f5a265421391cc3ad0075740087ffffffff0100000000000000000e6a0c31d52bf3b404aefaf596cfd000000000"
        config.PREFIX = b'CNTRPRTY'
        parsed_source, parsed_destination, parsed_btc_amount, parsed_fee, parsed_data, extra = blocks._get_tx_info(
            datatxhex)
        print('!!!!!!!!!!!!!!!!>1')
        print(parsed_source)
        print(parsed_destination)
        print(parsed_btc_amount)
        print(parsed_fee)
        print(parsed_data)
        print(extra)
        print('!!!!!!!!!!!!!!!!<1')
Example #4
0
def test_bytespersigop(server_db):
    assert util.enabled('bytespersigop') == False

    # ADDR[0], bytespersigop=False, desc 41 bytes, opreturn
    txhex = api.compose_transaction(
        server_db, 'issuance',
        {'source': ADDR[0],
         'asset': 'TESTING',
         'quantity': 100,
         'transfer_destination': None,
         'divisible': False,
         'description': 't' * 41},
    )

    tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

    assert len(tx.vin) == 1
    assert len(tx.vout) == 2
    assert "OP_RETURN" in repr(tx.vout[0].scriptPubKey)

    # ADDR[0], bytespersigop=False, desc 42 bytes, multisig
    txhex = api.compose_transaction(
        server_db, 'issuance',
        {'source': ADDR[0],
         'asset': 'TESTING',
         'quantity': 100,
         'transfer_destination': None,
         'divisible': False,
         'description': 't' * 42},
    )

    tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

    assert len(tx.vin) == 1
    assert len(tx.vout) == 3
    assert "OP_CHECKMULTISIG" in repr(tx.vout[0].scriptPubKey)
    assert "OP_CHECKMULTISIG" in repr(tx.vout[1].scriptPubKey)

    # enable byterpersigop
    with util_test.MockProtocolChangesContext(bytespersigop=True):
        assert util.enabled('bytespersigop') == True

        # ADDR[0], bytespersigop=True, desc 41 bytes, opreturn
        txhex = api.compose_transaction(
            server_db, 'issuance',
            {'source': ADDR[0],
             'asset': 'TESTING',
             'quantity': 100,
             'transfer_destination': None,
             'divisible': False,
             'description': 't' * 41},
        )

        tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

        assert len(tx.vin) == 1
        assert len(tx.vout) == 2
        assert "OP_RETURN" in repr(tx.vout[0].scriptPubKey)

        # ADDR[0], bytespersigop=True, desc 42 bytes, pubkeyhash encoding
        #  pubkeyhash because ADDR[0] only has 1 UTXO to spend from
        txhex = api.compose_transaction(
            server_db, 'issuance',
            {'source': ADDR[0],
             'asset': 'TESTING',
             'quantity': 100,
             'transfer_destination': None,
             'divisible': False,
             'description': 't' * 42},
        )

        tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

        assert len(tx.vin) == 1
        assert len(tx.vout) == 8
        for i in range(7):
            assert "OP_CHECKSIG" in repr(tx.vout[i].scriptPubKey)

        # ADDR[0], bytespersigop=True, desc 20 bytes, FORCED multisig encoding
        #  will error because it's not possible, ADDR[0] only has 1 UTXO
        with pytest.raises(exceptions.EncodingError):
            txhex = api.compose_transaction(
                server_db, 'issuance',
                {'source': ADDR[0],
                 'asset': 'TESTING',
                 'quantity': 100,
                 'transfer_destination': None,
                 'divisible': False,
             'description': 't' * 20},
                encoding='multisig'
            )

        # ADDR[1], bytespersigop=True, desc 41 bytes, opreturn encoding
        txhex = api.compose_transaction(
            server_db, 'issuance',
            {'source': ADDR[1],
             'asset': 'TESTING',
             'quantity': 100,
             'transfer_destination': None,
             'divisible': False,
             'description': 't' * 41},
        )

        tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

        assert len(tx.vin) == 1
        assert len(tx.vout) == 2
        assert "OP_RETURN" in repr(tx.vout[0].scriptPubKey)

        # ADDR[1], bytespersigop=True, desc 20 bytes, FORCED encoding=multisig
        #  will use 2 UTXOs to make the bytes:sigop ratio in our favor
        txhex = api.compose_transaction(
            server_db, 'issuance',
            {'source': ADDR[1],
             'asset': 'TESTING',
             'quantity': 100,
             'transfer_destination': None,
             'divisible': False,
             'description': 't' * 20},
            encoding='multisig'
        )

        tx = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(txhex))

        assert len(tx.vin) == 2
        assert len(tx.vout) == 2
        assert "OP_CHECKMULTISIG" in repr(tx.vout[0].scriptPubKey)
def test_p2sh_encoding_manual_multisig_transaction(server_db):
    source = P2SH_ADDR[0]
    destination = ADDR[1]

    with util_test.ConfigContext(
            OLD_STYLE_API=True), util_test.MockProtocolChangesContext(
                enhanced_sends=True, p2sh_encoding=True):
        p2sh_source_multisig_pubkeys_binary = [
            binascii.unhexlify(p) for p in [
                DP['pubkey'][ADDR[0]], DP['pubkey'][ADDR[1]], DP['pubkey'][
                    ADDR[2]]
            ]
        ]
        scriptSig, redeemScript, outputScript = p2sh_encoding.make_p2sh_encoding_redeemscript(
            b'deadbeef01',
            n=0,
            pubKey=None,
            multisig_pubkeys=p2sh_source_multisig_pubkeys_binary,
            multisig_pubkeys_required=2)
        redeemScript = bitcoinlib.core.script.CScript(redeemScript)
        assert repr(
            redeemScript
        ) == "CScript([OP_DROP, 2, x('{}'), x('{}'), x('{}'), 3, OP_CHECKMULTISIGVERIFY, 0, OP_DROP, OP_DEPTH, 0, OP_EQUAL])".format(
            DP['pubkey'][ADDR[0]], DP['pubkey'][ADDR[1]],
            DP['pubkey'][ADDR[2]])

        # setup transaction
        fee = 20000
        fee_per_kb = 50000
        pretxhex = api.compose_transaction(
            server_db,
            'send', {
                'source': source,
                'destination': destination,
                'asset': 'XCP',
                'quantity': 100,
            },
            p2sh_source_multisig_pubkeys=[
                DP['pubkey'][ADDR[0]], DP['pubkey'][ADDR[1]],
                DP['pubkey'][ADDR[2]]
            ],
            p2sh_source_multisig_pubkeys_required=2,
            encoding='p2sh',
            fee_per_kb=fee_per_kb,
            fee=fee)
        # debugTransaction = bitcoinlib.core.CTransaction.deserialize(binascii.unhexlify(pretxhex))

        # store transaction
        pretxid, _ = util_test.insert_raw_transaction(pretxhex, server_db)
        logger.debug('pretxid %s' % (pretxid))

        # now compose the data transaction
        result = api.compose_transaction(
            server_db,
            'send',
            {
                'source': source,
                'destination': destination,
                'asset': 'XCP',
                'quantity': 100
            },
            p2sh_source_multisig_pubkeys=[
                DP['pubkey'][ADDR[0]], DP['pubkey'][ADDR[1]],
                DP['pubkey'][ADDR[2]]
            ],
            p2sh_source_multisig_pubkeys_required=2,
            p2sh_pretx_txid=pretxid,  # pass the pretxid
            encoding='p2sh',
            fee_per_kb=fee_per_kb)
        assert not isinstance(result, list)
        datatxhex = result

        datatx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(datatxhex))

        # parse the transaction
        parsed_source, parsed_destination, parsed_btc_amount, parsed_fee, parsed_data, extra = blocks._get_tx_info(
            datatxhex)
        assert parsed_source == source
        assert parsed_data == binascii.unhexlify(
            "00000002"
            "0000000000000001"
            "0000000000000064"
            "6f8d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec"
        )  # ID=enhanced_send(0x02) ASSET=XCP(0x01) VALUE=100(0x64) destination_pubkey(0x6f8d...d6ec)
        assert parsed_btc_amount == 0
def test_p2sh_encoding(server_db):
    source = ADDR[0]
    destination = ADDR[1]

    with util_test.ConfigContext(
            OLD_STYLE_API=True), util_test.MockProtocolChangesContext(
                enhanced_sends=True, p2sh_encoding=True):
        utxos = dict(((utxo['txid'], utxo['vout']), utxo)
                     for utxo in backend.get_unspent_txouts(source))

        # pprint.pprint(utxos)

        fee = 20000
        fee_per_kb = 50000
        result = api.compose_transaction(server_db,
                                         'send', {
                                             'source': source,
                                             'destination': destination,
                                             'asset': 'XCP',
                                             'quantity': 100
                                         },
                                         encoding='p2sh',
                                         fee_per_kb=fee_per_kb,
                                         fee=fee)
        assert not isinstance(result, list)
        pretxhex = result

        pretx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(pretxhex))

        sumvin = sum([
            int(utxos[(bitcoinlib.core.b2lx(
                vin.prevout.hash), vin.prevout.n)]['amount'] * 1e8)
            for vin in pretx.vin
        ])
        sumvout = sum([vout.nValue for vout in pretx.vout])

        assert len(pretx.vout) == 2
        assert len(pretxhex) / 2 == 142
        assert sumvin == 199909140
        assert sumvout < sumvin
        assert sumvout == (sumvin - fee)

        # data P2SH output
        expected_datatx_length = 435
        expected_datatx_fee = int(expected_datatx_length / 1000 * fee_per_kb)
        assert repr(
            pretx.vout[0].scriptPubKey
        ) == "CScript([OP_HASH160, x('7698101f9b9e5cdf0a0e11c2972dbc4860f374bf'), OP_EQUAL])"
        assert pretx.vout[0].nValue == expected_datatx_fee
        # change output
        assert pretx.vout[1].nValue == sumvin - expected_datatx_fee - fee

        assert pretxhex == "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff02f65400000000000017a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87febbe90b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
        # 01000000                                                          | version
        # 01                                                                | inputs
        # c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae  | txout hash
        # 00000000                                                          | txout index
        # 19                                                                | script length
        # 76a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac                | tx_script
        # ffffffff                                                          | Sequence
        # 02                                                                | number of outputs
        # f654000000000000                                                  | output 1 value (21750)
        # 17                                                                | output 1 length (23 bytes)
        # a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87                    | output 1 script
        # febbe90b00000000                                                  | output 2 value (199867390)
        # 19                                                                | output 2 length (25 bytes)
        # 76a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac                | output 2 script
        # 00000000                                                          | locktime

        # first transaction should be considered BTC only
        with pytest.raises(exceptions.BTCOnlyError):
            blocks._get_tx_info(pretxhex)

        # store transaction
        pretxid, _ = util_test.insert_raw_transaction(pretxhex, server_db)

        logger.debug('pretxid %s' % (pretxid))

        # check that when we do another, unrelated, send that it won't use our UTXO
        result = api.compose_transaction(
            server_db, 'send', {
                'source': source,
                'destination': destination,
                'asset': 'XCP',
                'quantity': 100
            })
        othertx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(result))
        othertxid = bitcoinlib.core.lx(
            bitcoinlib.core.b2x(othertx.vin[0].prevout.hash))  # reverse hash
        assert not (binascii.hexlify(othertxid).decode('ascii') == pretxid
                    and othertx.vin[0].prevout.n == 0)

        # now compose the data transaction
        result = api.compose_transaction(
            server_db,
            'send',
            {
                'source': source,
                'destination': destination,
                'asset': 'XCP',
                'quantity': 100
            },
            p2sh_pretx_txid=pretxid,  # pass the pretxid
            encoding='p2sh',
            fee_per_kb=fee_per_kb)
        assert not isinstance(result, list)
        datatxhex = result

        datatx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(datatxhex))
        sumvin = sum(
            [pretx.vout[n].nValue for n, vin in enumerate(datatx.vin)])
        sumvout = sum([vout.nValue for vout in datatx.vout])
        fee = 10000

        assert len(datatxhex) / 2 == 190
        assert sumvin == expected_datatx_fee
        assert sumvout < sumvin
        assert sumvout == sumvin - expected_datatx_fee
        assert len(datatx.vout) == 1
        # opreturn signalling P2SH
        assert repr(
            datatx.vout[0].scriptPubKey
        ) == "CScript([OP_RETURN, x('8a5dda15fb6f0562da344d2f')])"  # arc4(PREFIX + 'P2SH')
        assert datatx.vout[0].nValue == 0

        assert datatxhex == "01000000010a0746fe9308ac6e753fb85780a8b788b40655148dcde1435f2048783b784f06000000007431544553545858585800000002000000000000000100000000000000646f8d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec2975210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0ad007574008717a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87ffffffff0100000000000000000e6a0c8a5dda15fb6f0562da344d2f00000000"
        # 01000000                                                                                    | version
        # 01                                                                                          | inputs
        # 0a0746fe9308ac6e753fb85780a8b788b40655148dcde1435f2048783b784f06                            | txout hash
        # 00000000                                                                                    | txout index (0)
        # 74                                                                                          | script length (116)
        # 31544553545858585800000002000000000000000100000000000000                                    | tx_script
        #         646f8d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec2975210282b886c087eb37dc8182f14ba6cc    |   ...
        #         3e9485ed618b95804d44aecc17c300b585b0ad007574008717a9147698101f9b9e5cdf0a0e11c297    |   ...
        #         2dbc4860f374bf87                                                                    |   ...
        # ffffffff                                                                                    | Sequence
        # 01                                                                                          | number of outputs
        # 0000000000000000                                                                            | output 1 value (0)
        # 0e                                                                                          | output 1 length (14 bytes)
        # 6a0c8a5dda15fb6f0562da344d2f                                                                | output 1 script
        # 00000000                                                                                    | locktime

        # verify parsed result
        parsed_source, parsed_destination, parsed_btc_amount, parsed_fee, parsed_data, extra = blocks._get_tx_info(
            datatxhex)
        assert parsed_source == source
        assert parsed_data == binascii.unhexlify(
            "00000002"
            "0000000000000001"
            "0000000000000064"
            "6f8d6ae8a3b381663118b4e1eff4cfc7d0954dd6ec"
        )  # ID=enhanced_send(0x02) ASSET=XCP(0x01) VALUE=100(0x64) destination_pubkey(0x6f8d...d6ec)
        assert parsed_btc_amount == 0
        assert parsed_fee == expected_datatx_fee

        # check signing pubkey
        tx_script_start = 8 + 2 + 64 + 8
        tx_script_length = int(datatxhex[tx_script_start:tx_script_start + 2],
                               16) * 2
        tx_script = datatxhex[tx_script_start + 2:tx_script_start + 2 +
                              tx_script_length]
        signing_pubkey_hash = tx_script[-44:-4]
        address = script.base58_check_encode(signing_pubkey_hash,
                                             config.ADDRESSVERSION)
def test_p2sh_encoding_long_data(server_db):
    source = ADDR[0]
    destination = ADDR[1]

    with util_test.ConfigContext(
            OLD_STYLE_API=True), util_test.MockProtocolChangesContext(
                enhanced_sends=True, p2sh_encoding=True):
        utxos = dict(((utxo['txid'], utxo['vout']), utxo)
                     for utxo in backend.get_unspent_txouts(source))

        # pprint.pprint(utxos)

        fee_per_kb = 50000
        result = api.compose_transaction(
            server_db,
            'broadcast', {
                'source': source,
                'text': 'The quick brown fox jumped over the lazy dog. ' * 12,
                'fee_fraction': 0,
                'timestamp': 1512155862,
                'value': 0,
            },
            encoding='p2sh',
            fee_per_kb=fee_per_kb)
        assert not isinstance(result, list)
        pretxhex = result

        pretx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(pretxhex))
        actual_fee = int(len(pretxhex) / 2 * fee_per_kb / 1000)

        sumvin = sum([
            int(utxos[(bitcoinlib.core.b2lx(
                vin.prevout.hash), vin.prevout.n)]['amount'] * 1e8)
            for vin in pretx.vin
        ])
        sumvout = sum([vout.nValue for vout in pretx.vout])

        pretx_fee = 12950

        assert len(pretx.vout) == 3
        assert len(pretxhex) / 2 == 174
        assert sumvin == 199909140
        assert sumvout < sumvin
        assert sumvout == (sumvin - pretx_fee)

        # data P2SH output
        expected_datatx_length = 1156
        expected_datatx_fee = int(expected_datatx_length / 1000 * fee_per_kb)
        expected_datatx_fee_rounded = int(math.ceil(
            expected_datatx_fee / 2)) * 2
        assert repr(
            pretx.vout[0].scriptPubKey
        ) == "CScript([OP_HASH160, x('7698101f9b9e5cdf0a0e11c2972dbc4860f374bf'), OP_EQUAL])"
        assert pretx.vout[0].nValue == int(math.ceil(expected_datatx_fee / 2))
        assert pretx.vout[1].nValue == int(math.ceil(expected_datatx_fee / 2))
        # change output
        assert pretx.vout[
            2].nValue == sumvin - expected_datatx_fee_rounded - pretx_fee

        assert pretxhex == "0100000001c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788acffffffff03e47000000000000017a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87e47000000000000017a914676d587edf25cf01d3b153ff0b71f5e9b622386387b64ae90b000000001976a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac00000000"
        # 00000001                                                         | version
        # 01                                                               | inputs
        # c1d8c075936c3495f6d653c50f73d987f75448d97a750249b1eb83bee71b24ae | txout hash
        # 00000000                                                         | txout index
        # 19                                                               | script length
        # 76a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac               | tx_script
        # ffffffff                                                         | Sequence
        # 03                                                               | number of outputs (3)
        # e470000000000000                                                 | output 1 value (28900)
        # 17                                                               | output 1 length (23 bytes)
        # a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87                   | output 1 script
        # e470000000000000                                                 | output 2 value (28900)
        # 17                                                               | output 2 length (23 bytes)
        # a914676d587edf25cf01d3b153ff0b71f5e9b622386387                   | output 2 script
        # b64ae90b00000000                                                 | output 3 value (199838390)
        # 19                                                               | output 3 length (25 bytes)
        # 76a9144838d8b3588c4c7ba7c1d06f866e9b3739c6303788ac               | output 3 script
        # 00000000                                                         | locktime

        # store transaction
        pretxid, _ = util_test.insert_raw_transaction(pretxhex, server_db)
        logger.debug('pretxid %s' % (pretxid))

        # now compose the data transaction
        result = api.compose_transaction(
            server_db,
            'broadcast',
            {
                'source': source,
                'text': 'The quick brown fox jumped over the lazy dog. ' * 12,
                'fee_fraction': 0,
                'timestamp': 1512155862,
                'value': 0,
            },
            p2sh_pretx_txid=pretxid,  # pass the pretxid
            encoding='p2sh',
            fee_per_kb=fee_per_kb)
        assert not isinstance(result, list)
        datatxhex = result

        datatx = bitcoinlib.core.CTransaction.deserialize(
            binascii.unhexlify(datatxhex))
        sumvin = sum(
            [pretx.vout[n].nValue for n, vin in enumerate(datatx.vin)])
        sumvout = sum([vout.nValue for vout in datatx.vout])
        assert len(datatx.vin) == 2

        assert len(datatxhex) / 2 == 1682 / 2
        assert sumvin == expected_datatx_fee_rounded
        assert sumvout < sumvin
        assert sumvout == sumvin - expected_datatx_fee_rounded
        assert len(datatx.vout) == 1
        # opreturn signalling P2SH
        assert repr(
            datatx.vout[0].scriptPubKey
        ) == "CScript([OP_RETURN, x('8a5dda15fb6f0562da344d2f')])"  # arc4(PREFIX + 'P2SH')
        assert datatx.vout[0].nValue == 0
        assert datatxhex == "0100000002f33f677de4180f1b0c261a991974c57de97f082a7e62332b77ec5d193d13d1a300000000fd4d024d080254455354585858580000001e5a21aad600000000000000000000000054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f766572202975210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0ad007574008717a9147698101f9b9e5cdf0a0e11c2972dbc4860f374bf87fffffffff33f677de4180f1b0c261a991974c57de97f082a7e62332b77ec5d193d13d1a30100000087445445535458585858746865206c617a7920646f672e2054686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e202975210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0ad517574008717a914676d587edf25cf01d3b153ff0b71f5e9b622386387ffffffff0100000000000000000e6a0c8a5dda15fb6f0562da344d2f00000000"
        # 01000000                                                                                              | version
        # 02                                                                                                    | inputs
        # f33f677de4180f1b0c261a991974c57de97f082a7e62332b77ec5d193d13d1a3                                      | txout hash
        # 00000000                                                                                              | txout index (0)
        # fd                                                                                                    | script length (253)
        # 4d024d080254455354585858580000001e5a21aad6000000000000000000000000                                    | tx_script
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e20      |   ...
        #     54686520717569636b2062726f776e20666f78206a756d706564206f766572202975210282b886c087eb37dc8182      |   ...
        #     f14ba6cc3e9485ed618b95804d44aecc17c300b585b0ad007574008717a9147698101f9b9e5cdf0a0e11c2972dbc      |   ...
        #     4860f374bf87                                                                                      |   ...
        # ffffffff                                                                                              | Sequence
        # f33f677de4180f1b0c261a991974c57de97f082a7e62332b77ec5d193d13d1a3                                      | txout hash
        # 01000000                                                                                              | txout index (1)
        # 87                                                                                                    | script length (135)
        # 445445535458585858746865206c617a7920646f672e20                                                        | tx_script
        #     54686520717569636b2062726f776e20666f78206a756d706564206f76657220746865206c617a7920646f672e202975  |   ...
        #     210282b886c087eb37dc8182f14ba6cc3e9485ed618b95804d44aecc17c300b585b0ad517574008717a914676d587edf  |   ...
        #     25cf01d3b153ff0b71f5e9b622386387                                                                  |   ...
        # ffffffff                                                                                              | Sequence
        # 01                                                                                                    | number of outputs
        # 0000000000000000                                                                                      | output 1 value (0)
        # 0e                                                                                                    | output 1 length (14 bytes)
        # 6a0c8a5dda15fb6f0562da344d2f                                                                          | output 1 script
        # 00000000                                                                                              | locktime

        # verify parsed result
        parsed_source, parsed_destination, parsed_btc_amount, parsed_fee, parsed_data, extra = blocks._get_tx_info(
            datatxhex)
        assert parsed_source == source

        assert parsed_data == binascii.unhexlify(
            "0000001e5a21aad6000000000000000000000000"
        ) + b'The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog. '  # ID=enhanced_send(0x1e) ASSET=XCP(0x01) VALUE=100(0x64) destination_pubkey(0x6f8d...d6ec)
        assert parsed_btc_amount == 0
        assert parsed_fee == expected_datatx_fee_rounded