예제 #1
0
    def test_sending_between_p2sh_1of2_and_p2wpkh_p2sh(self, mock_write):
        wallet1a = WalletIntegrityHelper.create_multisig_wallet(
            [
                keystore.from_seed('phone guilt ancient scan defy gasp off rotate approve ill word exchange', '', True),
                keystore.from_xpub('tpubD6NzVbkrYhZ4YPZ3ntVjqSCxiUUv2jikrUBU73Q3iJ7Y8iR41oYf991L5fanv7ciHjbjokdK2bjYqg1BzEUDxucU9qM5WRdBiY738wmgLP4')
            ],
            '1of2', gap_limit=2
        )
        # ^ second seed: kingdom now gift initial age right velvet exotic harbor enforce kingdom kick
        wallet2 = WalletIntegrityHelper.create_standard_wallet(
            # bip39: uniform tank success logic lesson awesome stove elegant regular desert drip device, der: m/49'/1'/0'
            keystore.from_xprv('uprv91HGbrNZTK4x8u22nbdYGzEuWPxjaHMREUi7CNhY64KsG5ZGnVM99uCa16EMSfrnaPTFxjbRdBZ2WiBkokoM8anzAy3Vpc52o88WPkitnxi'),
            gap_limit=2
        )

        # bootstrap wallet1
        funding_tx = Transaction('010000000001027e20990282eb29588375ad04936e1e991af3bc5b9c6f1ab62eca8c25becaef6a01000000171600140e6a17fadc8bafba830f3467a889f6b211d69a00fdffffff51847fd6bcbdfd1d1ea2c2d95c2d8de1e34c5f2bd9493e88a96a4e229f564e800100000017160014ecdf9fa06856f9643b1a73144bc76c24c67774a6fdffffff021e8501000000000017a91451991bfa68fbcb1e28aa0b1e060b7d24003352e38700093d000000000017a914b0b9f31bace76cdfae2c14abc03e223403d7dc4b870247304402205e19721b92c6afd70cd932acb50815a36ee32ab46a934147d62f02c13aeacf4702207289c4a4131ef86e27058ff70b6cb6bf0e8e81c6cbab6dddd7b0a9bc732960e4012103fe504411c21f7663caa0bbf28931f03fae7e0def7bc54851e0194dfb1e2c85ef02483045022100e969b65096fba4f8b24eb5bc622d2282076241621f3efe922cc2067f7a8a6be702203ec4047dd2a71b9c83eb6a0875a6d66b4d65864637576c06ed029d3d1a8654b0012102bbc8100dca67ba0297aba51296a4184d714204a5fc2eda34708360f37019a3dccfcc1300')
        funding_txid = funding_tx.txid()
        funding_output_value = 4000000
        self.assertEqual('1137c12de4ce0f5b08de8846ba14c0814351a7f0f31457c8ea51a5d4b3c891a3', funding_txid)
        wallet1a.receive_tx_callback(funding_txid, funding_tx, TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 1000000)]
        tx = wallet1a.mktx(outputs=outputs, password=None, config=self.config, fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1a.is_mine(tx.inputs()[0]['address']), wallet1a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual('1b7e94860b9681d4e371928d40fdbd4641e991aa74f1a211f239c887047e4a2a', tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(), 300000)]
        tx = wallet2.mktx(outputs=outputs, password=None, config=self.config, fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2.is_mine(tx.inputs()[0]['address']), wallet2.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual('f65edb0843ff44436dc5964fb6b298e157502b9b4a83dac6b82dd2d2a3247d0a', tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 1000000 - 5000 + 300000, 0), wallet1a.get_balance())
        self.assertEqual((0, 1000000 - 5000 - 300000, 0), wallet2.get_balance())
예제 #2
0
    def test_sending_between_p2wpkh_and_compressed_p2pkh(self, mock_write):
        wallet1 = self.create_standard_wallet_from_seed('bitter grass shiver impose acquire brush forget axis eager alone wine silver')
        wallet2 = self.create_standard_wallet_from_seed('cycle rocket west magnet parrot shuffle foot correct salt library feed song')

        # bootstrap wallet1
        funding_tx = Transaction('01000000014576dacce264c24d81887642b726f5d64aa7825b21b350c7b75a57f337da6845010000006b483045022100a3f8b6155c71a98ad9986edd6161b20d24fad99b6463c23b463856c0ee54826d02200f606017fd987696ebbe5200daedde922eee264325a184d5bbda965ba5160821012102e5c473c051dae31043c335266d0ef89c1daab2f34d885cc7706b267f3269c609ffffffff0240420f00000000001600148a28bddb7f61864bdcf58b2ad13d5aeb3abc3c42a2ddb90e000000001976a914c384950342cb6f8df55175b48586838b03130fad88ac00000000')
        funding_txid = funding_tx.txid()
        funding_output_value = 1000000
        self.assertEqual('add2535aedcbb5ba79cc2260868bb9e57f328738ca192937f2c92e0e94c19203', funding_txid)
        wallet1.receive_tx_callback(funding_txid, funding_tx, TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(), 250000)]
        tx = wallet1.mktx(outputs=outputs, password=None, config=self.config, fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1.is_mine(tx.inputs()[0]['address']), wallet1.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual('3c06ae4d9be8226a472b3e7f7c127c7e3016f525d658d26106b80b4c7e3228e2', tx_copy.txid())

        wallet1.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)  # TX_HEIGHT_UNCONF_PARENT but nvm
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1.get_receiving_address(), 100000)]
        tx = wallet2.mktx(outputs=outputs, password=None, config=self.config, fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2.is_mine(tx.inputs()[0]['address']), wallet2.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual('5f25707571eb776bdf14142f9966bf2a681906e0a79501edbb99a972c2ceb972', tx_copy.txid())

        wallet1.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 250000 - 5000 + 100000, 0), wallet1.get_balance())
        self.assertEqual((0, 250000 - 5000 - 100000, 0), wallet2.get_balance())
    def test_sending_between_p2wsh_2of3_and_p2wsh_p2sh_2of2(self, mock_write):
        wallet1a = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'bitter grass shiver impose acquire brush forget axis eager alone wine silver',
                '', True),
            keystore.from_xpub(
                'Vpub5fcdcgEwTJmbmqAktuK8Kyq92fMf7sWkcP6oqAii2tG47dNbfkGEGUbfS9NuZaRywLkHE6EmUksrqo32ZL3ouLN1HTar6oRiHpDzKMAF1tf'
            ),
            keystore.from_xpub(
                'Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'
            ),
            gap_limit=2)
        wallet1b = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'snow nest raise royal more walk demise rotate smooth spirit canyon gun',
                '', True),
            keystore.from_xpub(
                'Vpub5fjkKyYnvSS4wBuakWTkNvZDaBM2vQ1MeXWq368VJHNr2eT8efqhpmZ6UUkb7s2dwCXv2Vuggjdhk4vZVyiAQTwUftvff73XcUGq2NQmWra'
            ),
            keystore.from_xpub(
                'Vpub5gSKXzxK7FeKQedu2q1z9oJWxqvX72AArW3HSWpEhc8othDH8xMDu28gr7gf17sp492BuJod8Tn7anjvJrKpETwqnQqX7CS8fcYyUtedEMk'
            ),
            gap_limit=2)
        # ^ third seed: hedgehog sunset update estate number jungle amount piano friend donate upper wool
        wallet2a = WalletIntegrityHelper.create_multisig_wallet(
            # bip39: finish seminar arrange erosion sunny coil insane together pretty lunch lunch rose, der: m/1234'/1'/0', p2wsh-p2sh multisig
            keystore.from_xprv(
                'Uprv9CvELvByqm8k2dpecJVjgLMX1z5DufEjY4fBC5YvdGF5WjGCa7GVJJ2fYni1tyuF7Hw83E6W2ZBjAhaFLZv2ri3rEsubkCd5avg4EHKoDBN'
            ),
            keystore.from_xpub(
                'Upub5Qb8ik4Cnu8g97KLXKgVXHqY6tH8emQvqtBncjSKsyfTZuorPtTZgX7ovKKZHuuVGBVd1MTTBkWez1XXt2weN1sWBz6SfgRPQYEkNgz81QF'
            ),
            gap_limit=2)
        wallet2b = WalletIntegrityHelper.create_multisig_wallet(
            # bip39: square page wood spy oil story rebel give milk screen slide shuffle, der: m/1234'/1'/0', p2wsh-p2sh multisig
            keystore.from_xprv(
                'Uprv9BbnKEXJxXaNvdEsRJ9VA9toYrSeFJh5UfGBpM2iKe8Uh7UhrM9K8ioL53s8gvCoGfirHHaqpABDAE7VUNw8LNU1DMJKVoWyeNKu9XcDC19'
            ),
            keystore.from_xpub(
                'Upub5RuakRisg8h3F7u7iL2k3UJFa1uiK7xauHamzTxYBbn4PXbM7eajr6M9Q2VCr6cVGhfhqWQqxnABvtSATuVM1xzxk4nA189jJwzaMn1QX7V'
            ),
            gap_limit=2)

        # bootstrap wallet1
        funding_tx = Transaction(
            '01000000000101a41aae475d026c9255200082c7fad26dc47771275b0afba238dccda98a597bd20000000000fdffffff02400d0300000000002200203c43ac80d6e3015cf378bf6bac0c22456723d6050bef324ec641e7762440c63c9dcd410000000000160014824626055515f3ed1d2cfc9152d2e70685c71e8f02483045022100b9f39fad57d07ce1e18251424034f21f10f20e59931041b5167ae343ce973cf602200fefb727fa0ffd25b353f1bcdae2395898fe407b692c62f5885afbf52fa06f5701210301a28f68511ace43114b674371257bb599fd2c686c4b19544870b1799c954b40e9c11300'
        )
        funding_txid = funding_tx.txid()
        funding_output_value = 200000
        self.assertEqual(
            'd2bd6c9d332db8e2c50aa521cd50f963fba214645aab2f7556e061a412103e21',
            funding_txid)
        wallet1a.receive_tx_callback(funding_txid, funding_tx,
                                     TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2a.get_receiving_address(),
                    165000)]
        tx = wallet1a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet1b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1a.is_mine(tx.inputs()[0]['address']),
                         wallet1a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '6e9c3cd8788bdb970a124ea06136d52bc01cec4f9b1e217627d5e90ebe77d049',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(),
                    100000)]
        tx = wallet2a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet2b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertTrue(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2a.is_mine(tx.inputs()[0]['address']),
                         wallet2a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '84b0dcb43022385f7a10e2710e5625a2be3cd6e390387b6100b55500d5eea8f6',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 165000 - 5000 + 100000, 0),
                         wallet1a.get_balance())
        self.assertEqual((0, 165000 - 5000 - 100000, 0),
                         wallet2a.get_balance())
    def test_sending_between_p2sh_2of3_and_uncompressed_p2pkh(
            self, mock_write):
        wallet1a = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'blast uniform dragon fiscal ensure vast young utility dinosaur abandon rookie sure',
                '', True),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'
            ),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4XJzYkhsCbDCcZRmDAKSD7bXi9mdCni7acVt45fxbTVZyU6jRGh29ULKTjoapkfFsSJvQHitcVKbQgzgkkYsAmaovcro7Mhf'
            ),
            gap_limit=2)
        wallet1b = WalletIntegrityHelper.create_multisig_wallet(
            keystore.from_seed(
                'cycle rocket west magnet parrot shuffle foot correct salt library feed song',
                '', True),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YTPEgwk4zzr8wyo7pXGmbbVUnfYNtx6SgAMF5q3LN3Kch58P9hxGNsTmP7Dn49nnrmpE6upoRb1Xojg12FGLuLHkVpVtS44'
            ),
            keystore.from_xpub(
                'tpubD6NzVbkrYhZ4YARFMEZPckrqJkw59GZD1PXtQnw14ukvWDofR7Z1HMeSCxfYEZVvg4VdZ8zGok5VxHwdrLqew5cMdQntWc5mT7mh1CSgrnX'
            ),
            gap_limit=2)
        # ^ third seed: ghost into match ivory badge robot record tackle radar elbow traffic loud
        wallet2 = self.create_standard_wallet_from_seed(
            'powerful random nobody notice nothing important anyway look away hidden message over'
        )

        # bootstrap wallet1
        funding_tx = Transaction(
            '010000000001014121f99dc02f0364d2dab3d08905ff4c36fc76c55437fd90b769c35cc18618280100000000fdffffff02d4c22d00000000001600143fd1bc5d32245850c8cb5be5b09c73ccbb9a0f75001bb7000000000017a91480c2353f6a7bc3c71e99e062655b19adb3dd2e4887024830450221008781c78df0c9d4b5ea057333195d5d76bc29494d773f14fa80e27d2f288b2c360220762531614799b6f0fb8d539b18cb5232ab4253dd4385435157b28a44ff63810d0121033de77d21926e09efd04047ae2d39dbd3fb9db446e8b7ed53e0f70f9c9478f735dac11300'
        )
        funding_txid = funding_tx.txid()
        funding_output_value = 12000000
        self.assertEqual(
            'b25cd55687c9e528c2cfd546054f35fb6741f7cf32d600f07dfecdf2e1d42071',
            funding_txid)
        wallet1a.receive_tx_callback(funding_txid, funding_tx,
                                     TX_HEIGHT_UNCONFIRMED)

        # wallet1 -> wallet2
        outputs = [(bitcoin.TYPE_ADDRESS, wallet2.get_receiving_address(),
                    370000)]
        tx = wallet1a.mktx(outputs=outputs,
                           password=None,
                           config=self.config,
                           fee=5000)
        tx = Transaction(
            tx.serialize())  # simulates moving partial txn between cosigners
        self.assertFalse(tx.is_complete())
        wallet1b.sign_transaction(tx, password=None)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet1a.is_mine(tx.inputs()[0]['address']),
                         wallet1a.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet1a.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet1a.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            '26f3bdd0402e1cff19126244ebe3d32722cef0db507c7229ca8754f5e06ef25d',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet2 -> wallet1
        outputs = [(bitcoin.TYPE_ADDRESS, wallet1a.get_receiving_address(),
                    100000)]
        tx = wallet2.mktx(outputs=outputs,
                          password=None,
                          config=self.config,
                          fee=5000)

        self.assertTrue(tx.is_complete())
        self.assertFalse(tx.is_segwit())
        self.assertEqual(1, len(tx.inputs()))
        tx_copy = Transaction(tx.serialize())
        self.assertEqual(wallet2.is_mine(tx.inputs()[0]['address']),
                         wallet2.is_mine(tx_copy.inputs()[0]['address']))
        self.assertTrue(wallet2.is_mine(tx.inputs()[0]['address']))
        self.assertEqual(wallet2.txin_type, tx_copy.inputs()[0]['type'])
        self.assertEqual(tx.wtxid(), tx_copy.wtxid())
        self.assertEqual(
            'c573b3f8464a4ed40dfc79d0889a780f44e917beef7a75883b2427c2987f3e95',
            tx_copy.txid())

        wallet1a.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)
        wallet2.receive_tx_callback(tx.txid(), tx, TX_HEIGHT_UNCONFIRMED)

        # wallet level checks
        self.assertEqual((0, funding_output_value - 370000 - 5000 + 100000, 0),
                         wallet1a.get_balance())
        self.assertEqual((0, 370000 - 5000 - 100000, 0), wallet2.get_balance())
    def test_inputs(self):
        try:
            with open(txintests_local) as f:
                testlist = json.load(f)
            print("Got script tests from %s; will not download." %
                  (txintests_local, ))
        except IOError:
            print("Couldn't get script tests from %s; downloading from %s..." %
                  (txintests_local, txintests_url))
            testlist = requests.get(txintests_url).json()

        print("Starting %d tests on SLP's input validation" % len(testlist))
        for test in testlist:
            description = test['description']

            given_validity = {}
            #should_validity = {}
            txes = {}
            for d in test['when']:
                tx = Transaction(d['tx'])
                txid = tx.txid()
                txes[txid] = tx
                if d['valid'] is True:
                    given_validity[txid] = 1
                elif d['valid'] is False:
                    given_validity[txid] = 2
                else:
                    raise ValueError(d['valid'])

            for d in test['should']:
                tx = Transaction(d['tx'])
                txid = tx.txid()
                txes[txid] = tx
                d['txid'] = txid
                #if d['valid'] is True:
                #should_validity[txid] = 1
                #elif d['valid'] is False:
                #should_validity[txid] = 2
                #else:
                #raise ValueError(d['valid'])

            for i, d in enumerate(test['should']):
                txid = d['txid']
                with self.subTest(description=description, i=i):
                    try:
                        graph, jobmgr = slp_validator_0x01.setup_job(
                            txes[txid], reset=True)
                    except slp.SlpInvalidOutputMessage:  # If output 0 is not OP_RETURN
                        self.assertEqual(d['valid'], False)
                        continue

                    def fetch_hook(txids):
                        l = []
                        for txid in txids:
                            try:
                                l.append(txes[txid])
                            except KeyError:
                                pass
                        ### Call proxy here!
                        return l

                    job = slp_validator_0x01.ValidationJob(
                        graph, [txid],
                        None,
                        fetch_hook=fetch_hook,
                        validitycache=given_validity)
                    #if txid == '8a08b78ae434de0b1a26e56ae7e78bb11b20f8240eb3d97371fd46a609df7fc3':
                    #graph.debugging = True
                    #job.debugging_graph_state = True
                    q = Queue()
                    job.add_callback(q.put)
                    jobmgr.add_job(job)
                    try:
                        q.get(timeout=3)  # unlimited timeout
                    except Empty:
                        raise RuntimeError(
                            "Timeout during validation unit test")

                    n = next(iter(job.nodes.values()))
                    if d['valid'] is True:
                        self.assertEqual(n.validity, 1)
                    elif d['valid'] is False:
                        self.assertIn(n.validity, (2, 3))
                    else:
                        raise ValueError(d['valid'])
예제 #6
0
    def test_inputs(self):
        try:
            with open(txintests_local) as f:
                testlist = json.load(f)
            print("Got script tests from %s; will not download." %
                  (txintests_local, ))
        except IOError:
            print("Couldn't get script tests from %s; downloading from %s..." %
                  (txintests_local, txintests_url))
            testlist = requests.get(txintests_url).json()

        print("Starting %d tests on SLP's input validation" % len(testlist))
        for test in testlist:
            description = test['description']

            given_validity = {}
            #should_validity = {}
            txes = {}
            for d in test['when']:
                tx = Transaction(d['tx'])
                txid = tx.txid()
                txes[txid] = tx
                if d['valid'] is True:
                    given_validity[txid] = 1
                elif d['valid'] is False:
                    given_validity[txid] = 2
                else:
                    raise ValueError(d['valid'])

            for d in test['should']:
                tx = Transaction(d['tx'])
                txid = tx.txid()
                txes[txid] = tx
                d['txid'] = txid
                #if d['valid'] is True:
                #should_validity[txid] = 1
                #elif d['valid'] is False:
                #should_validity[txid] = 2
                #else:
                #raise ValueError(d['valid'])

            graph_context, graph_context_nft1 = slp_validator_0x01.GraphContext(
            ), slp_validator_0x01_nft1.GraphContext_NFT1()

            for i, d in enumerate(test['should']):
                txid = d['txid']
                with self.subTest(description=description, i=i):
                    try:
                        slp_msg = slp.SlpMessage.parseSlpOutputScript(
                            txes[txid].outputs()[0][1])
                        if slp_msg.token_type == 1:
                            graph, job_mgr = graph_context.setup_job(
                                txes[txid], reset=True)
                        elif slp_msg.token_type == 65 or slp_msg.token_type == 129:
                            graph, job_mgr = graph_context_nft1.setup_job(
                                txes[txid], reset=True)
                        else:
                            raise slp.SlpUnsupportedSlpTokenType(
                                slp_msg.token_type)
                    except slp.SlpInvalidOutputMessage:  # If output 0 is not OP_RETURN
                        self.assertEqual(d['valid'], False)
                        continue
                    except slp.SlpUnsupportedSlpTokenType:
                        self.assertEqual(d['valid'], False)
                        continue

                    def fetch_hook(txids, job):
                        l = []
                        for txid in txids:
                            try:
                                l.append(txes[txid])
                            except KeyError:
                                #raise Exception('KEY ERROR ' + txid)
                                pass
                        ### Call proxy here!
                        return l

                    if slp_msg.token_type == 1:
                        job = slp_validator_0x01.ValidationJob(
                            graph,
                            txid,
                            None,
                            fetch_hook=fetch_hook,
                            validitycache=given_validity)
                    elif slp_msg.token_type == 65:
                        network = MockNetwork(txes)
                        storage = WalletStorage(os.path.curdir,
                                                manual_upgrades=True,
                                                in_memory_only=True)
                        wallet = Slp_ImportedAddressWallet(storage)
                        wallet.slp_graph_0x01_nft = graph_context_nft1
                        #raise Exception(txid)
                        job = slp_validator_0x01_nft1.ValidationJobNFT1Child(
                            graph,
                            txid,
                            network,
                            fetch_hook=fetch_hook,
                            validitycache=None,
                            ref=wallet)
                    elif slp_msg.token_type == 129:
                        job = slp_validator_0x01_nft1.ValidationJob(
                            graph,
                            txid,
                            None,
                            fetch_hook=fetch_hook,
                            validitycache=given_validity)
                    #if txid == '8a08b78ae434de0b1a26e56ae7e78bb11b20f8240eb3d97371fd46a609df7fc3':
                    #graph.debugging = True
                    #job.debugging_graph_state = True
                    q = Queue()
                    job.add_callback(q.put)
                    job_mgr.add_job(job)
                    while True:
                        try:
                            q.get(timeout=3)  # unlimited timeout
                        except Empty:
                            raise RuntimeError(
                                "Timeout during validation unit test")
                        # if isinstance(job, ValidationJobNFT1Child) and not job.paused:# and job.stop_reason != 'inconclusive':
                        #     raise Exception(job.stop_reason)
                        if not job.paused and not job.running:  # and job.stop_reason != 'inconclusive':
                            n = next(iter(job.nodes.values()))
                            if d['valid'] is True:
                                self.assertEqual(n.validity, 1)
                            elif d['valid'] is False:
                                if test.get(
                                        'allow_inconclusive', False
                                ):  # "allow_inconclusive" allows for ending with an "unvalidated" state for harder corner-cases
                                    self.assertIn(n.validity, (0, 2, 3, 4))
                                else:
                                    self.assertIn(n.validity, (2, 3, 4))
                            else:
                                raise ValueError(d['valid'])
                            break
                        else:
                            if len(job.callbacks) > 1:
                                raise Exception(
                                    "shouldn't have more than 1 callback")
                            job.callbacks.clear()
                            job.add_callback(q.put, allow_run_cb_now=False)