Exemplo n.º 1
0
    def run_test(self):
        node0_address = self.nodes[0].getnewaddress()
        # Spend block 1/2/3's coinbase transactions
        # Mine a block.
        # Create three more transactions, spending the spends
        # Mine another block.
        # ... make sure all the transactions are confirmed
        # Invalidate both blocks
        # ... make sure all the transactions are put back in the mempool
        # Mine a new block
        # ... make sure all the transactions are confirmed again.

        b = [self.nodes[0].getblockhash(n) for n in range(1, 4)]
        coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
        spends1_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids]
        spends1_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw]

        blocks = []
        blocks.extend(self.nodes[0].generate(1, self.signblockprivkey_wif))

        spends2_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.98) for txid in spends1_id]
        spends2_id = [self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw]

        blocks.extend(self.nodes[0].generate(1, self.signblockprivkey_wif))

        # mempool should be empty, all txns confirmed
        assert_equal(set(self.nodes[0].getrawmempool()), set())
        for txid in spends1_id+spends2_id:
            tx = self.nodes[0].gettransaction(txid)
            assert(tx["confirmations"] > 0)

        # Use invalidateblock to re-org back
        for node in self.nodes:
            node.invalidateblock(blocks[0])

        color_ids=[create_colored_transaction(2, 1000, self.nodes[0])['txid'], create_colored_transaction(3, 1, self.nodes[0])['txid']]
        blocks.extend(self.nodes[0].generate(1, self.signblockprivkey_wif))

        # mempool should be empty, all txns confirmed 
        assert_equal(set(self.nodes[0].getrawmempool()), set())

        # Use invalidate to re-org back 
        for node in self.nodes:
            node.invalidateblock(blocks[2])

        # All txns should be back in mempool with 0 confirmations
        assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id+color_ids))
        for txid in spends1_id+spends2_id+color_ids:
            tx = self.nodes[0].gettransaction(txid)
            assert(tx["confirmations"] == 0)

        # Generate another block, they should all get mined
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        # mempool should be empty, all txns confirmed
        assert_equal(set(self.nodes[0].getrawmempool()), set())
        for txid in spends1_id+spends2_id+color_ids:
            tx = self.nodes[0].gettransaction(txid)
            assert(tx["confirmations"] > 0)
    def run_test(self):

        self.log.info("Cresting blocks")
        self.nodes[0].generate(2, self.signblockprivkey_wif)
        self.sync_all()
        self.nodes[1].generate(2, self.signblockprivkey_wif)
        self.sync_all()
        self.nodes[2].generate(2, self.signblockprivkey_wif)
        self.sync_all()

        self.log.info("Testing token issue using create_colored_transaction ")
        new_color1 = create_colored_transaction(1, 1000,
                                                self.nodes[0])['color']
        new_color2 = create_colored_transaction(2, 1000,
                                                self.nodes[1])['color']
        new_color3 = create_colored_transaction(3, 1, self.nodes[2])['color']

        self.sync_all()
        self.nodes[2].generate(1, self.signblockprivkey_wif)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color1], 1000)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color2], 1000)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color3], 1)

        self.log.info(
            "Testing token transfer using create_colored_transaction ")
        create_colored_transaction(1, 500, self.nodes[0], False, new_color1,
                                   self.nodes[1])
        create_colored_transaction(2, 500, self.nodes[1], False, new_color2,
                                   self.nodes[2])
        create_colored_transaction(3, 1, self.nodes[2], False, new_color3,
                                   self.nodes[0])

        self.sync_all()
        self.nodes[2].generate(1, self.signblockprivkey_wif)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color1], 500)
        assert_equal(walletinfo['balance'][new_color3], 1)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color2], 500)
        assert_equal(walletinfo['balance'][new_color1], 500)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(walletinfo['balance'][new_color3], 0)
        assert_equal(walletinfo['balance'][new_color2], 500)
Exemplo n.º 3
0
    def run_test(self):
        """Run the test using the labels API."""
        node = self.nodes[0]

        # Check that there's no UTXO on any of the nodes
        assert_equal(len(node.listunspent()), 0)

        # Note each time we call generate, all generated coins go into
        # the same address, so we call twice to get two addresses w/50 each
        node.generate(1, self.signblockprivkey_wif)
        node.generate(1, self.signblockprivkey_wif)
        assert_equal(node.getbalance(), 100)
        assert_equal(len(node.listunspent()), 2)

        # there should be 2 address groups
        # each with 1 address with a balance of 50 TPC
        address_groups = node.listaddressgroupings()
        assert_equal(len(address_groups), 2)
        # the addresses aren't linked now, but will be after we send to the
        # common address
        linked_addresses = set()
        for address_group in address_groups:
            assert_equal(len(address_group), 1)
            assert_equal(len(address_group[0]), 2)
            assert_equal(address_group[0][1], 50)
            linked_addresses.add(address_group[0][0])

        # send 50 from each address to a third address not in this wallet
        # There's some fee that will come back to us when the miner reward
        # matures.
        common_address = "msf4WtN1YQKXvNtvdFYt9JBnUD2FB41kjr"
        txid = node.sendmany(amounts={common_address: 100},
                             subtractfeefrom=[common_address])
        tx_details = node.gettransaction(txid)
        fee = -tx_details['details'][0]['fee']
        # there should be 1 address group, with the previously
        # unlinked addresses now linked (they both have 0 balance)
        address_groups = node.listaddressgroupings()
        assert_equal(len(address_groups), 1)
        assert_equal(len(address_groups[0]), 2)
        assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses)
        assert_equal([a[1] for a in address_groups[0]], [0, 0])

        node.generate(1, self.signblockprivkey_wif)

        amount_to_send = 1.0

        self.log.debug("Checking lables with TPC")
        # Create labels and make sure subsequent label API calls
        # recognize the label/address associations.
        labels = [Label(name) for name in ("a", "b", "c", "d", "e")]
        for label in labels:
            address = node.getnewaddress(label.name)
            label.add_address(address)
            label.verify(node)

        # Check all labels are returned by listlabels.
        assert_equal(node.listlabels(), [label.name for label in labels])

        # Send a transaction to each label, and make sure this forces
        # getaccountaddress to generate a new receiving address.
        for label in labels:
            node.sendtoaddress(label.addresses[0], amount_to_send)
            label.verify(node)

        # Check the amounts received.
        node.generate(1, self.signblockprivkey_wif)
        for label in labels:
            assert_equal(node.getreceivedbyaddress(label.addresses[0]),
                         amount_to_send)
            assert_equal(node.getreceivedbylabel(label.name),
                         {'TPC': Decimal('1.00000000')})

        # generate extra blocks so that they can be used in token issue.
        node.generate(6, self.signblockprivkey_wif)

        self.log.debug("Checking lables with tokens")
        colorId = create_colored_transaction(2, 10, node)['color']
        for label in labels:
            address = node.getnewaddress(label.name, colorId)
            label.add_coloraddress(address)

        #separate calls to getaddressinfo to avoid race conditin in address book reading when getnewaddress and getaddressinfo are in the same loop''
        for label in labels:
            label.verify(node, colorId)

        # Send a transaction to each label, and make sure this forces
        # getaccountaddress to generate a new receiving address.
        for label in labels:
            node.sendtoaddress(label.caddresses[0], 1)
            label.verify(node, colorId)

        # Check the amounts received.
        node.generate(1, self.signblockprivkey_wif)
        for label in labels:
            assert_equal(node.getreceivedbyaddress(label.caddresses[0]), 1)
            assert_equal(node.getreceivedbyaddress(label.addresses[0]),
                         amount_to_send)
            assert_equal(node.getreceivedbylabel(label.name), {
                'TPC': Decimal('1.00000000'),
                colorId: 1
            })

        self.log.debug(
            "Check that sendfrom label reduces listaccounts balances in TPC")
        for i, label in enumerate(labels):
            to_label = labels[(i + 1) % len(labels)]
            node.sendtoaddress(to_label.addresses[0], amount_to_send)
        node.generate(1, self.signblockprivkey_wif)
        for label in labels:
            address = node.getnewaddress(label.name)
            label.add_address(address)
            label.verify(node)
            assert_equal(node.getreceivedbylabel(label.name), {
                'TPC': Decimal('2.00000000'),
                colorId: 1
            })
            label.verify(node)
        node.generate(3, self.signblockprivkey_wif)
        assert_equal(math.floor(node.getbalance()), 650)

        self.log.debug(
            "Check that sendfrom label reduces listaccounts balances in tokens"
        )
        for i, label in enumerate(labels):
            to_label = labels[(i + 1) % len(labels)]
            node.sendtoaddress(to_label.caddresses[0], 1)
        node.generate(1, self.signblockprivkey_wif)
        for label in labels:
            address = node.getnewaddress(label.name, colorId)
            label.add_coloraddress(address)
            label.verify(node, colorId)
            assert_equal(node.getreceivedbylabel(label.name), {
                'TPC': Decimal('2.0000000'),
                colorId: 2
            })
            label.verify(node, colorId)
        node.generate(3, self.signblockprivkey_wif)
        assert_equal(math.floor(node.getbalance()), 850)

        # Check that setlabel can assign a label to a new unused address.
        for label in labels:
            address = node.getnewaddress()
            node.setlabel(address, label.name)
            label.add_address(address)
            label.verify(node)
            assert_raises_rpc_error(-11, "No addresses with label",
                                    node.getaddressesbylabel, "")

        # Check that addmultisigaddress can assign labels.
        for label in labels:
            addresses = []
            for x in range(10):
                addresses.append(node.getnewaddress())
            multisig_address = node.addmultisigaddress(5, addresses,
                                                       label.name)['address']
            label.add_address(multisig_address)
            label.purpose[multisig_address] = "send"
            label.verify(node)

        node.generate(1, self.signblockprivkey_wif)

        # Check that setlabel can change the label of an address from a
        # different label.
        change_label(node, labels[0].addresses[0], labels[0], labels[1])

        # Check that setlabel can set the label of an address already
        # in the label. This is a no-op.
        change_label(node, labels[2].addresses[0], labels[2], labels[2])
Exemplo n.º 4
0
    def run_test(self):
        # Check that nodes don't own any UTXOs
        assert_equal(len(self.nodes[0].listunspent()), 0)
        assert_equal(len(self.nodes[1].listunspent()), 0)

        self.log.info("Mining one block for each node")

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        colorid1 = create_colored_transaction(2, 100, self.nodes[0])['color']
        self.nodes[0].generatetoaddress(1, RANDOM_COINBASE_ADDRESS,
                                        self.signblockprivkey_wif)
        self.sync_all()
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        colorid2 = create_colored_transaction(2, 100, self.nodes[1])['color']
        self.nodes[1].generatetoaddress(1, RANDOM_COINBASE_ADDRESS,
                                        self.signblockprivkey_wif)
        self.sync_all()

        assert_equal(self.nodes[0].getbalance(), Decimal('49.99995520'))
        wallet_bal = self.nodes[0].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid1], 100)
        assert_equal(self.nodes[1].getbalance(), Decimal('49.99995520'))
        wallet_bal = self.nodes[1].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid2], 100)

        self.log.info("Test getbalance with different arguments")
        assert_equal(self.nodes[0].getbalance(True), Decimal('49.99995520'))
        assert_equal(self.nodes[1].getbalance(True), Decimal('49.99995520'))

        # Send 40 TPC from 0 to 1 and 60 BTC from 1 to 0.
        txs = create_transactions(self.nodes[0], 'TPC',
                                  self.nodes[1].getnewaddress(), 40,
                                  [Decimal('0.01')])
        self.nodes[0].sendrawtransaction(txs[0]['hex'])
        self.nodes[1].sendrawtransaction(
            txs[0]['hex']
        )  # sending on both nodes is faster than waiting for propagation
        self.sync_all()

        txs = create_transactions(
            self.nodes[1], 'TPC', self.nodes[0].getnewaddress(), 60,
            [Decimal('0.01'), Decimal('0.04')])
        self.nodes[1].sendrawtransaction(txs[0]['hex'])
        self.nodes[0].sendrawtransaction(txs[0]['hex'])
        self.sync_all()

        self.log.info(
            "Test getbalance and getunconfirmedbalance with unconfirmed inputs"
        )

        # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
        assert_equal(round(self.nodes[0].getbalance(), 2),
                     Decimal('9.99'))  # change from node 0's send
        assert_equal(round(self.nodes[1].getbalance(), 2),
                     Decimal('29.99'))  # change from node 1's send

        # getunconfirmedbalance
        assert_equal(self.nodes[0].getunconfirmedbalance(),
                     Decimal('60'))  # output of node 1's spend
        assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal(
            '0'))  # Doesn't include output of node 0's send since it was spent

        # Send 40 colorid1 from 0 to 1 and 60 colorid2 from 1 to 0.
        ctxs = create_transactions(self.nodes[0], colorid1,
                                   self.nodes[1].getnewaddress("", colorid1),
                                   40, [Decimal('0.01')])
        self.nodes[0].sendrawtransaction(ctxs[0]['hex'])
        self.nodes[1].sendrawtransaction(ctxs[0]['hex'])
        self.sync_all()

        ctxs = create_transactions(self.nodes[1], colorid2,
                                   self.nodes[0].getnewaddress("", colorid2),
                                   60, [Decimal('0.01')])
        self.nodes[1].sendrawtransaction(ctxs[0]['hex'])
        self.nodes[0].sendrawtransaction(ctxs[0]['hex'])
        self.sync_all()

        # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
        assert_equal(round(self.nodes[0].getbalance(), 2), Decimal('9.98'))
        assert_equal(round(self.nodes[1].getbalance(), 2), Decimal('29.98'))
        wallet_bal = self.nodes[0].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid1], 60)
        assert_equal(len(wallet_bal), 2)
        wallet_bal = self.nodes[1].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid2], 40)
        assert_equal(len(wallet_bal), 2)

        # getunconfirmedbalance
        assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60'))
        assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0'))
        wallet_bal = self.nodes[0].getwalletinfo()['unconfirmed_balance']
        assert_equal(len(wallet_bal), 1)
        wallet_bal = self.nodes[1].getwalletinfo()['unconfirmed_balance']
        assert_equal(len(wallet_bal), 1)

        # Node 1 bumps the transaction fee and resends
        self.nodes[1].sendrawtransaction(txs[1]['hex'])
        self.sync_all()

        self.log.info(
            "Test getbalance and getunconfirmedbalance with conflicted unconfirmed inputs"
        )

        assert_equal(
            self.nodes[0].getwalletinfo()["unconfirmed_balance"]['TPC'],
            Decimal('60'))  # output of node 1's send
        assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60'))
        assert_equal(
            self.nodes[1].getwalletinfo()["unconfirmed_balance"]['TPC'],
            Decimal('0')
        )  # Doesn't include output of node 0's send since it was spent
        assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('0'))

        self.nodes[1].generatetoaddress(1, RANDOM_COINBASE_ADDRESS,
                                        self.signblockprivkey_wif)
        self.sync_all()

        # balances are correct after the transactions are confirmed
        assert_equal(
            round(self.nodes[0].getbalance(), 2),
            Decimal('69.98'))  # node 1's send plus change from node 0's send
        assert_equal(round(self.nodes[1].getbalance(), 2),
                     Decimal('29.96'))  # change from node 0's send

        wallet_bal = self.nodes[0].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid1], 60)
        wallet_bal = self.nodes[1].getwalletinfo()['balance']
        assert_equal(wallet_bal[colorid2], 100)

        # Send total balance away from node 1
        txs = create_transactions(self.nodes[1], 'TPC',
                                  self.nodes[0].getnewaddress(),
                                  Decimal('29.94995520'), [Decimal('0.01')])
        self.nodes[1].sendrawtransaction(txs[0]['hex'])
        self.nodes[1].generatetoaddress(2, RANDOM_COINBASE_ADDRESS,
                                        self.signblockprivkey_wif)
        self.sync_all()

        assert_equal(self.nodes[1].getbalance(), Decimal('0'))
Exemplo n.º 5
0
    def run_test(self):
        # Generate block to get out of IBD
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        sync_blocks(self.nodes)

        self.log.info("listreceivedbyaddress Test")

        # Send from node 0 to 1
        addr = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(addr, 0.1)
        self.sync_all()

        # Check not listed in listreceivedbyaddress because has 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr},
                            {},
                            True)
        # Bury Tx under 10 block so it will be returned by listreceivedbyaddress
        self.nodes[1].generate(10, self.signblockprivkey_wif)
        self.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr},
                            {"address": addr, "label": "", "token": "TPC", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})

        # Empty Tx
        empty_addr = self.nodes[1].getnewaddress()
        assert_array_result(self.nodes[1].listreceivedbyaddress(True),
                            {"address": empty_addr},
                            {"address": empty_addr, "label": "", "token": "TPC", "amount": 0, "confirmations": 0, "txids": []})

        # Test Address filtering
        # Only on addr
        expected = {"address": addr, "label": "", "token": "TPC", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
        res = self.nodes[1].listreceivedbyaddress(include_empty=True, include_watchonly=True, address_filter=addr)
        assert_array_result(res, {"address": addr}, expected)
        assert_equal(len(res), 1)
        # Error on invalid address
        assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, include_empty=True, include_watchonly=True, address_filter="bamboozling")
        # Another address receive money
        res = self.nodes[1].listreceivedbyaddress(True, True)
        assert_equal(len(res), 2)  # Right now 2 entries
        other_addr = self.nodes[1].getnewaddress()
        txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()
        # Same test as above should still pass
        expected = {"address": addr, "label": "", "token": "TPC", "amount": Decimal("0.1"), "confirmations": 11, "txids": [txid, ]}
        res = self.nodes[1].listreceivedbyaddress(True, True, addr)
        assert_array_result(res, {"address": addr}, expected)
        assert_equal(len(res), 1)
        # Same test as above but with other_addr should still pass
        expected = {"address": other_addr, "label": "", "token": "TPC", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]}
        res = self.nodes[1].listreceivedbyaddress(True, True, other_addr)
        assert_array_result(res, {"address": other_addr}, expected)
        assert_equal(len(res), 1)
        # Should be two entries though without filter
        res = self.nodes[1].listreceivedbyaddress(True, True)
        assert_equal(len(res), 3)  # Became 3 entries

        # Not on random addr
        other_addr = self.nodes[0].getnewaddress()  # note on node[0]! just a random addr
        res = self.nodes[1].listreceivedbyaddress(True, True, other_addr)
        assert_equal(len(res), 0)

        self.log.info("getreceivedbyaddress Test")

        # Send from node 0 to 1
        addr = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(addr, 0.1)
        self.sync_all()

        # Check balance is 0 because of 0 confirmations
        balance = self.nodes[1].getreceivedbyaddress(addr)
        assert_equal(balance, Decimal("0.0"))

        # Check balance is 0.1
        balance = self.nodes[1].getunconfirmedbalance()
        assert_equal(balance, Decimal("0.1"))

        # Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
        self.nodes[1].generate(10, self.signblockprivkey_wif)
        self.sync_all()
        balance = self.nodes[1].getreceivedbyaddress(addr)
        assert_equal(balance, Decimal("0.1"))

        # Trying to getreceivedby for an address the wallet doesn't own should return an error
        assert_raises_rpc_error(-4, "Address not found in wallet", self.nodes[0].getreceivedbyaddress, addr)

        self.log.info("listreceivedbylabel + getreceivedbylabel Test")

        # set pre-state
        label = ''
        address = self.nodes[1].getnewaddress()
        assert_equal(self.nodes[1].getaddressinfo(address)['label'], label)
        received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
        balance_by_label = self.nodes[1].getreceivedbylabel(label)

        txid = self.nodes[0].sendtoaddress(addr, 0.1)
        self.sync_all()

        # listreceivedbylabel should return received_by_label_json because of 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"label": label},
                            received_by_label_json)

        # getreceivedbyaddress should return same balance because of 0 confirmations
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance, balance_by_label)

        self.nodes[1].generate(10, self.signblockprivkey_wif)
        self.sync_all()
        # listreceivedbylabel should return updated received list
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"label": label},
                            {"label": received_by_label_json["label"], 
                             "token": 'TPC',
                             "amount": (received_by_label_json["amount"] + Decimal("0.1"))})

        # getreceivedbylabel should return updated receive total
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance['TPC'], balance_by_label['TPC'] + Decimal("0.1"))

        # Create a new label named "mynewlabel" that has a 0 balance
        address = self.nodes[1].getnewaddress()
        self.nodes[1].setlabel(address, "mynewlabel")
        received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(True) if r["label"] == "mynewlabel"][0]

        # Test includeempty of listreceivedbylabel
        assert_equal(received_by_label_json["amount"], Decimal("0.0"))

        # Test getreceivedbylabel for 0 amount labels
        balance = self.nodes[1].getreceivedbylabel("mynewlabel")
        assert_equal(balance, {})

        self.log.info("listreceivedbylabel + getreceivedbylabel Test with tokens")

        colorId = create_colored_transaction(1, 10, self.nodes[0])['color']

        address = self.nodes[1].getnewaddress("", colorId)
        assert_equal(self.nodes[1].getaddressinfo(address)['label'], label)
        received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
        balance_by_label = self.nodes[1].getreceivedbylabel(label)

        txid = self.nodes[0].sendtoaddress(address, 1)
        self.sync_all()

        # listreceivedbylabel should return received_by_label_json because of 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"label": label},
                            received_by_label_json)

        # getreceivedbyaddress should return same balance because of 0 confirmations
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance, balance_by_label)

        self.nodes[1].generate(10, self.signblockprivkey_wif)
        self.sync_all()
        # listreceivedbylabel should return updated received list
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"token": colorId},
                            {"label": received_by_label_json["label"], 
                             "amount": 1})

        # getreceivedbylabel should return updated receive total
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance[colorId], 1)

        # Create a new label named "mynewlabel" that has a 0 balance
        address = self.nodes[1].getnewaddress("", colorId)
        self.nodes[1].setlabel(address, "mynewcolorlabel")
        received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(True) if r["label"] == "mynewcolorlabel"][0]

        # Test includeempty of listreceivedbylabel
        assert_equal(received_by_label_json["amount"], Decimal("0.0"))

        # Test getreceivedbylabel for 0 amount labels
        balance = self.nodes[1].getreceivedbylabel("mynewcolorlabel")
        assert_equal(balance, {})
    def run_test(self):
        node = self.nodes[0]  # convenience reference to the node
        self.address = node.getnewaddress()
        node.add_p2p_connection(P2PDataStore())
        node.p2p.wait_for_getheaders(timeout=5)

        self.log.info("Test starting...")

        #genesis block (B0)
        self.blocks = [self.genesisBlock.hash]
        block_time = self.genesisBlock.nTime

        # Create a new blocks B1 - B10
        self.blocks += node.generate(1, self.aggprivkey_wif[0])
        create_colored_transaction(2, 100, node)
        self.blocks += node.generate(9, self.aggprivkey_wif[0])
        best_block = node.getblock(node.getbestblockhash())
        self.tip = node.getbestblockhash()

        self.log.info("First federation block")
        # B11 - Create block - aggpubkey2 - sign with aggpubkey1
        block_time = best_block["time"] + 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(11),
                                block_time, self.aggpubkeys[1])
        blocknew.solve(self.aggprivkey[0])
        self.blocks += [blocknew.hash]

        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = self.blocks[-1]
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B -- Create block with invalid aggpubkey2 - sign with aggpubkey1 -- failure - invalid aggpubkey
        aggpubkeyInv = self.aggpubkeys[-1][:-2]
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(12),
                                block_time, aggpubkeyInv)
        blocknew.solve(self.aggprivkey[0])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        # B - Create block - sign with aggpubkey1 - failure - Proof verification failed
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(12),
                                block_time)
        blocknew.solve(self.aggprivkey[0])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        # B12 - Create block - sign with aggpubkey2
        blocknew.solve(self.aggprivkey[1])
        self.blocks += [blocknew.hash]

        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = self.blocks[-1]
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        # Create a new blocks B13 - B22
        self.blocks += node.generate(10, self.aggprivkey_wif[1])
        best_block = node.getblock(node.getbestblockhash())
        self.tip = node.getbestblockhash()

        #B23 -- Create block with 1 valid transaction - sign with aggpubkey2 -- success
        block_time = best_block["time"] + 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(23),
                                block_time)
        spendHash = node.getblock(self.blocks[2])['tx'][1]
        vout = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            spendHash, 1)["vout"]) if vout["value"] != 100)
        rawtx = node.createrawtransaction(inputs=[{
            "txid": spendHash,
            "vout": vout
        }],
                                          outputs={self.address: 1.0})
        signresult = node.signrawtransactionwithwallet(rawtx, [], "ALL",
                                                       self.options.scheme)
        assert_equal(signresult["complete"], True)
        tx = CTransaction()
        tx.deserialize(BytesIO(hex_str_to_bytes(signresult['hex'])))
        blocknew.vtx += [tx]
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[1])
        self.blocks.append(blocknew.hash)
        self.tip = blocknew.hash
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #call invalidate block rpc on B23 -- success - B23 is removed from the blockchain. tip is B22
        node.invalidateblock(self.tip)
        self.tip = self.blocks[22]
        assert_equal(self.tip, node.getbestblockhash())

        #B23 -- Re Create a new block B23 -- success
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(23),
                                block_time)
        spendHash = node.getblock(self.blocks[2])['tx'][0]
        blocknew.vtx += [
            create_transaction(node, spendHash, self.address, amount=49.0)
        ]
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[1])
        self.blocks[22] = blocknew.hash
        self.tip = blocknew.hash
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B -- - Create block with 1 invalid transaction - sign with aggpubkey2 -- failure
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(23),
                                block_time)
        spendHash = node.getblock(self.blocks[3])['tx'][0]
        blocknew.vtx += [
            create_transaction(node, spendHash, self.address, amount=100.0)
        ]  #invalid
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[1])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        #B -- - Create block with 1 invalid transaction and aggpubkey3 - sign with aggpubkey2 -- failure and aggpubkey3 is not added to the list
        blocknew = create_block(int(self.tip, 16), create_coinbase(23),
                                block_time, self.aggpubkeys[2])
        spendHash = node.getblock(self.blocks[4])['tx'][0]
        blocknew.vtx += [
            create_transaction(node, spendHash, self.address, amount=100.0)
        ]  #invalid
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[1])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        # verify aggpubkey3 is not added to the list : verify that block signed using aggprivkey3 is rejected
        blocknew = create_block(int(self.tip, 16), create_coinbase(24),
                                block_time, self.aggpubkeys[2])
        blocknew.solve(self.aggprivkey[2])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        self.log.info("Second federation block")
        #B24 -- Create block with 1 valid transaction and aggpubkey3- sign with aggpubkey2 -- success and aggpubkey3 is added to the list
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(24),
                                block_time, self.aggpubkeys[2])
        spendHash = node.getblock(self.blocks[4])['tx'][0]
        blocknew.vtx += [
            create_transaction(node, spendHash, self.address, amount=10.0)
        ]
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[1])
        self.blocks.append(blocknew.hash)
        self.tip = blocknew.hash
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B25 -- Create block with 1 valid transaction - sign with aggpubkey3 -- success
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(25),
                                block_time)
        spendHash = node.getblock(self.blocks[5])['tx'][0]
        blocknew.vtx += [
            create_transaction(node, spendHash, self.address, amount=10.0)
        ]
        blocknew.hashMerkleRoot = blocknew.calc_merkle_root()
        blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root()
        blocknew.solve(self.aggprivkey[2])
        self.blocks.append(blocknew.hash)
        self.tip = blocknew.hash
        b25 = blocknew.hash
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        # Create a new blocks B26 - B30
        self.blocks += node.generate(5, self.aggprivkey_wif[2])
        best_block = node.getblock(node.getbestblockhash())
        self.tip = node.getbestblockhash()

        self.log.info("Verifying getblockchaininfo")
        #getblockchaininfo
        expectedAggPubKeys = [{
            self.aggpubkeys[0]: 0
        }, {
            self.aggpubkeys[1]: 12
        }, {
            self.aggpubkeys[2]: 25
        }]
        blockchaininfo = node.getblockchaininfo()
        assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys)

        self.log.info(
            "Simulate Blockchain Reorg  - After the last federation block")
        #B27 -- Create block with previous block hash = B26 - sign with aggpubkey3 -- success - block is accepted but there is no re-org
        block_time += 1
        self.forkblocks = self.blocks
        blocknew = create_block(int(self.blocks[26], 16), create_coinbase(27),
                                block_time)
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks[27] = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B28 -- Create block with previous block hash = B27 - sign with aggpubkey3 -- success - block is accepted but there is no re-org
        block_time += 1
        blocknew = create_block(int(self.forkblocks[27], 16),
                                create_coinbase(28), block_time)
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks[28] = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B29 -- Create block with previous block hash = B28 - sign with aggpubkey3 -- success - block is accepted but there is no re-org
        block_time += 1
        blocknew = create_block(int(self.forkblocks[28], 16),
                                create_coinbase(29), block_time)
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks[29] = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B30 -- Create block with previous block hash = B29 - sign with aggpubkey3 -- success - block is accepted but there is no re-org
        block_time += 1
        blocknew = create_block(int(self.forkblocks[29], 16),
                                create_coinbase(30), block_time)
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks[30] = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B31 -- Create block with previous block hash = B30 - sign with aggpubkey3 -- success - block is accepted and re-org happens
        block_time += 1
        blocknew = create_block(int(self.forkblocks[30], 16),
                                create_coinbase(31), block_time)
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks.append(blocknew.hash)
        self.tip = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys)

        self.log.info(
            "Simulate Blockchain Reorg  - Before the last federation block")
        #B24 -- Create block with previous block hash = B23 - sign with aggpubkey2 -- failure - block is in invalid chain
        block_time += 1
        blocknew = create_block(int(self.blocks[23], 16), create_coinbase(24),
                                block_time)
        blocknew.solve(self.aggprivkey[1])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B25 -- Create block with previous block hash = B24 - sign with aggpubkey2 -- success - block is in invalid chain
        block_time += 1
        blocknew = create_block(int(self.blocks[24], 16), create_coinbase(25),
                                block_time)
        blocknew.solve(self.aggprivkey[1])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #there are 3 tips in the current blockchain
        chaintips = node.getchaintips()
        assert_equal(len(chaintips), 3)

        assert (node.getblock(self.blocks[12]))
        assert (node.getblock(self.blocks[25]))
        assert_raises_rpc_error(-5, "Block not found", node.getblock,
                                blocknew.hash)

        self.log.info("Third Federation Block - active chain")
        #B32 -- Create block with aggpubkey4 - sign with aggpubkey3 -- success - aggpubkey4 is added to the list
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(32),
                                block_time, self.aggpubkeys[3])
        blocknew.solve(self.aggprivkey[2])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks.append(blocknew.hash)
        self.tip = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B -- Create block - sign with aggpubkey2 -- failure - proof verification failed
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(33),
                                block_time)
        blocknew.solve(self.aggprivkey[1])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        #B -- Create block - sign with aggpubkey3 -- failure - proof verification failed
        blocknew.solve(self.aggprivkey[2])
        assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())),
                     "invalid")
        assert_equal(self.tip, node.getbestblockhash())

        #B33 -- Create block  - sign with aggpubkey4 -- success
        blocknew.solve(self.aggprivkey[3])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.forkblocks.append(blocknew.hash)
        self.tip = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B34 - B35 -- Generate 2 blocks - no aggpubkey -- chain becomes longer
        self.forkblocks += node.generate(2, self.aggprivkey_wif[3])
        self.tip = self.forkblocks[35]
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        self.log.info("Fourth Federation Block")
        #B36 -- Create block with aggpubkey5 - sign using aggpubkey4 -- success - aggpubkey5 is added to the list
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(36),
                                block_time, self.aggpubkeys[4])
        blocknew.solve(self.aggprivkey[3])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = blocknew.hash
        self.forkblocks.append(blocknew.hash)
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #call invalidate block rpc on B36 -- failure - B36 is a federation block
        assert_raises_rpc_error(-8, "Federation block found",
                                node.invalidateblock, self.tip)
        assert_raises_rpc_error(-8, "Federation block found",
                                node.invalidateblock, self.forkblocks[33])
        assert_raises_rpc_error(-8, "Federation block found",
                                node.invalidateblock, self.blocks[29])
        assert_equal(self.tip, node.getbestblockhash())

        #B37 - Create block - sign using aggpubkey5 -- success
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(37),
                                block_time)
        blocknew.solve(self.aggprivkey[4])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = blocknew.hash
        self.forkblocks.append(blocknew.hash)
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        self.log.info("Verifying getblockchaininfo")
        #getblockchaininfo
        expectedAggPubKeys = [
            {
                self.aggpubkeys[0]: 0
            },
            {
                self.aggpubkeys[1]: 12
            },
            {
                self.aggpubkeys[2]: 25
            },
            {
                self.aggpubkeys[3]: 33
            },
            {
                self.aggpubkeys[4]: 37
            },
        ]
        blockchaininfo = node.getblockchaininfo()
        assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys)

        #B38 - B40 -- Generate 2 blocks - no aggpubkey -- chain becomes longer
        self.forkblocks += node.generate(3, self.aggprivkey_wif[4])
        self.tip = node.getbestblockhash()
        best_block = node.getblock(self.tip)

        self.log.info("Test Repeated aggpubkeys in Federation Block")
        #B41 -- Create block with aggpubkey0 - sign using aggpubkey5 -- success - aggpubkey0 is added to the list
        block_time = best_block["time"] + 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(41),
                                block_time, self.aggpubkeys[0])
        blocknew.solve(self.aggprivkey[4])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        #B42 -- Create block with aggpubkey1 - sign using aggpubkey0 -- success - aggpubkey1 is added to the list
        block_time += 1
        blocknew = create_block(int(self.tip, 16), create_coinbase(42),
                                block_time, self.aggpubkeys[1])
        blocknew.solve(self.aggprivkey[0])
        node.submitblock(bytes_to_hex_str(blocknew.serialize()))
        self.tip = blocknew.hash
        assert_equal(self.tip, node.getbestblockhash())
        assert (node.getblock(self.tip))

        self.log.info("Verifying getblockchaininfo")
        #getblockchaininfo
        expectedAggPubKeys = [
            {
                self.aggpubkeys[0]: 0
            },
            {
                self.aggpubkeys[1]: 12
            },
            {
                self.aggpubkeys[2]: 25
            },
            {
                self.aggpubkeys[3]: 33
            },
            {
                self.aggpubkeys[4]: 37
            },
            {
                self.aggpubkeys[0]: 42
            },
            {
                self.aggpubkeys[1]: 43
            },
        ]
        blockchaininfo = node.getblockchaininfo()
        assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys)
        self.stop_node(0)

        self.log.info("Restarting node with '-reindex-chainstate'")
        self.start_node(0, extra_args=["-reindex-chainstate"])
        self.sync_all()
        self.stop_node(0)

        self.log.info("Restarting node with '-loadblock'")
        shutil.copyfile(
            os.path.join(self.nodes[0].datadir, NetworkDirName(), 'blocks',
                         'blk00000.dat'),
            os.path.join(self.nodes[0].datadir, 'blk00000.dat'))
        os.remove(
            os.path.join(self.nodes[0].datadir, NetworkDirName(), 'blocks',
                         'blk00000.dat'))
        extra_args = [
            "-loadblock=%s" %
            os.path.join(self.nodes[0].datadir, 'blk00000.dat'), "-reindex"
        ]
        self.start_node(0, extra_args)
Exemplo n.º 7
0
    def run_test(self):
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        #create tokens
        colorId = create_colored_transaction(2, 100, self.nodes[0])['color']
        self.sync_all()
        self.nodes[2].generate(1, self.signblockprivkey_wif)

        # Create and fund a raw tx for sending 10 TPC
        psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']

        # Node 1 should not be able to add anything to it but still return the psbtx same as before
        psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt']
        assert_equal(psbtx1, psbtx)

        # Sign the transaction and send
        signed_tx = self.nodes[0].walletprocesspsbt(psbtx1)['psbt']
        final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
        self.nodes[0].sendrawtransaction(final_tx, True)

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        # Create and fund a raw tx for sending colored coin
        psbtx2 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress("tokenpsbt", colorId):10, self.nodes[0].getnewaddress("tokenpsbt", colorId):90})['psbt']

        psbtx = self.nodes[1].walletprocesspsbt(psbtx2)['psbt']
        assert_equal(psbtx2, psbtx)
        signed_tx = self.nodes[0].walletprocesspsbt(psbtx2)['psbt']

        final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
        self.nodes[0].sendrawtransaction(final_tx, True)

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        # Create p2sh and p2pkh addresses
        pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey']
        pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
        pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey']
        p2sh = self.nodes[1].addmultisigaddress(2, [pubkey0, pubkey1, pubkey2], "")['address']
        p2pkh = self.nodes[1].getnewaddress("")
        cp2pkh = self.nodes[1].getnewaddress("", colorId)

        # fund those addresses
        rawtx = self.nodes[0].createrawtransaction([], {p2sh:10, p2pkh:10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":2})
        rawtx = self.nodes[0].createrawtransaction([], {cp2pkh :10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx)
        rawtx = self.nodes[0].createrawtransaction([], {p2sh:30, p2pkh:30, cp2pkh : 10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx)
        signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'], [], "ALL", self.options.scheme)['hex']
        txid = self.nodes[0].sendrawtransaction(signed_tx, True)
        self.nodes[0].generate(6, self.signblockprivkey_wif)
        self.sync_all()

        # Find the output pos
        p2sh_pos = -1
        p2pkh_pos = -1
        decoded = self.nodes[0].decoderawtransaction(signed_tx)
        for out in decoded['vout']:
            if out['scriptPubKey']['addresses'][0] == p2sh:
                p2sh_pos = out['n']
            elif out['scriptPubKey']['addresses'][0] == p2pkh:
                p2pkh_pos = out['n']

        # spend single key from node 1
        rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'], True)

        # partially sign multisig things with node 1
        psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2sh_pos}], {self.nodes[1].getnewaddress():29.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
        psbtx = walletprocesspsbt_out['psbt']
        assert_equal(walletprocesspsbt_out['complete'], False)

        # partially sign with node 2. This should be complete and sendable
        walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[2].sendrawtransaction(self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'], True)

        # check that walletprocesspsbt fails to decode a non-psbt
        rawtx = self.nodes[1].createrawtransaction([{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():9.99})
        assert_raises_rpc_error(-22, "TX decode failed", self.nodes[1].walletprocesspsbt, rawtx)

        # Convert a non-psbt to psbt and make sure we can decode it
        rawtx = self.nodes[0].createrawtransaction([], {self.nodes[1].getnewaddress():10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx)
        new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
        self.nodes[0].decodepsbt(new_psbt)

        # Make sure that a psbt with signatures cannot be converted
        signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'], [], "ALL", self.options.scheme)
        assert_raises_rpc_error(-22, "Inputs must not have scriptSigs", self.nodes[0].converttopsbt, signedtx['hex'])

        # Explicilty allow converting non-empty txs
        new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
        self.nodes[0].decodepsbt(new_psbt)

        # Create outputs to nodes 1 and 2
        node1_addr = self.nodes[1].getnewaddress()
        node2_addr = self.nodes[2].getnewaddress()
        txid1 = self.nodes[0].sendtoaddress(node1_addr, 13)
        txid2 =self.nodes[0].sendtoaddress(node2_addr, 13)
        self.nodes[0].generate(6, self.signblockprivkey_wif)
        sync_blocks(self.nodes)
        #mempool is not synched.
        vout1 = find_output(self.nodes[1], txid1, 13)
        vout2 = find_output(self.nodes[2], txid2, 13)

        # Create a psbt spending outputs from nodes 1 and 2
        psbt_orig = self.nodes[0].createpsbt([{"txid":txid1,  "vout":vout1}, {"txid":txid2, "vout":vout2}], {self.nodes[0].getnewaddress():25.999})

        # Update psbts, should only have data for one input and not the other
        psbt1 = self.nodes[1].walletprocesspsbt(psbt_orig)['psbt']
        psbt1_decoded = self.nodes[0].decodepsbt(psbt1)
        assert psbt1_decoded['inputs'][0] and not psbt1_decoded['inputs'][1]
        psbt2 = self.nodes[2].walletprocesspsbt(psbt_orig)['psbt']
        psbt2_decoded = self.nodes[0].decodepsbt(psbt2)
        assert not psbt2_decoded['inputs'][0] and psbt2_decoded['inputs'][1]

        # Combine, finalize, and send the psbts
        combined = self.nodes[0].combinepsbt([psbt1, psbt2])
        finalized = self.nodes[0].finalizepsbt(combined)['hex']
        self.nodes[0].sendrawtransaction(finalized, True)
        self.nodes[0].generate(6, self.signblockprivkey_wif)
        sync_blocks(self.nodes)
        #mempool is not synched.

        # Test additional args in walletcreatepsbt
        # Make sure both pre-included and funded inputs
        # have the correct sequence numbers based on
        # replaceable arg
        block_height = self.nodes[0].getblockcount()
        unspent = self.nodes[0].listunspent()[0]
        psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"replaceable":True}, False)
        decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
        for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
           assert_equal(tx_in["sequence"], MAX_BIP125_RBF_SEQUENCE)
           assert "bip32_derivs" not in psbt_in
        assert_equal(decoded_psbt["tx"]["locktime"], block_height+2)

        # Same construction with only locktime set
        psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {}, True)
        decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
        for tx_in, psbt_in in zip(decoded_psbt["tx"]["vin"], decoded_psbt["inputs"]):
            assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
            assert "bip32_derivs" in psbt_in
        assert_equal(decoded_psbt["tx"]["locktime"], block_height)

        # Same construction without optional arguments
        psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
        decoded_psbt = self.nodes[0].decodepsbt(psbtx_info["psbt"])
        for tx_in in decoded_psbt["tx"]["vin"]:
            assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
        assert_equal(decoded_psbt["tx"]["locktime"], 0)


        # BIP 174 Test Vectors

        # Check that unknown values are just passed through
        unknown_psbt = "cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAACg8BAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAA="
        unknown_out = self.nodes[0].walletprocesspsbt(unknown_psbt)['psbt']
        assert_equal(unknown_psbt, unknown_out)

        # Open the data file
        with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json'), encoding='utf-8') as f:
            d = json.load(f)
            invalids = d['invalid']
            valids = d['valid']
            creators = d['creator']
            signers = d['signer']
            combiners = d['combiner']
            finalizers = d['finalizer']
            extractors = d['extractor']

        # Invalid PSBTs
        for invalid in invalids:
            assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decodepsbt, invalid)

        # Valid PSBTs
        for valid in valids:
            self.nodes[0].decodepsbt(valid)

        # Creator Tests
        for creator in creators:
            created_tx = self.nodes[0].createpsbt(creator['inputs'], creator['outputs'])
            assert_equal(created_tx, creator['result'])

        # Signer tests
        for i, signer in enumerate(signers):
            self.nodes[2].createwallet("wallet{}".format(i))
            wrpc = self.nodes[2].get_wallet_rpc("wallet{}".format(i))
            for key in signer['privkeys']:
                wrpc.importprivkey(key)
            signed_tx = wrpc.walletprocesspsbt(signer['psbt'])['psbt']
            assert_equal(signed_tx, signer['result'])

        # Combiner test
        for combiner in combiners:
            combined = self.nodes[2].combinepsbt(combiner['combine'])
            assert_equal(combined, combiner['result'])

        # Finalizer test
        for finalizer in finalizers:
            finalized = self.nodes[2].finalizepsbt(finalizer['finalize'], False)['psbt']
            assert_equal(finalized, finalizer['result'])

        # Extractor test
        for extractor in extractors:
            extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex']
            assert_equal(extracted, extractor['result'])
Exemplo n.º 8
0
    def run_test(self):
        # Start with a 1 block chain
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        assert_equal(self.nodes[0].getblockcount(), 1)

        # create a coloured coin transaction 
        res = create_colored_transaction(2, 1000, self.nodes[0])
        colorid = res['color']
        ctxid = res['txid']

        #new blocks to confirm the coin issue
        self.nodes[0].generate(10, self.signblockprivkey_wif)
        self.sync_all()

        #create multiple coiored coin outputs for use later
        txid_fee = self.nodes[0].getblock(self.nodes[0].getblockhash(2))['tx'][0]
        color_tx = self.nodes[0].createrawtransaction([{"txid": ctxid, "vout": 0}, {"txid": txid_fee, "vout": 0} ], [{self.nodes[0].getnewaddress("", colorid): 100}, {self.nodes[0].getnewaddress("", colorid): 100}, {self.nodes[0].getnewaddress("", colorid): 100}, {self.nodes[0].getnewaddress("", colorid): 100}, {self.nodes[1].getnewaddress("", colorid): 600}, {self.nodes[0].getnewaddress():49.99}])
        color_txid = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransactionwithwallet(color_tx, [], "ALL", self.options.scheme)["hex"])

        # Mine 3 blocks
        #  blocks 3 to 15 are spend-able.
        self.nodes[0].generate(5, self.signblockprivkey_wif)
        self.sync_all()

        #collect coinbase tx ids whose outputs will be spent or used as fee later
        b = [ self.nodes[0].getblockhash(n) for n in range(3, 15) ]
        coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]

        node0_address = self.nodes[0].getnewaddress()
        node1_address = self.nodes[1].getnewaddress()
        node0_caddress = self.nodes[0].getnewaddress("", colorid)
        node1_caddress = self.nodes[1].getnewaddress("", colorid)

        for (address_n0, address_n1, amt, height) in [(node0_address, node1_address, 49.99, 3), (node0_caddress, node1_caddress, 50, 7)]:
            # Three scenarios for re-orging coinbase spends in the memory pool:
            # 1. Direct coinbase spend  :  spend_101
            # 2. Indirect (coinbase spend in chain, child in mempool) : spend_102 and spend_102_1
            # 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
            # Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
            # and make sure the mempool code behaves correctly.
            self.log.info("From address [%s]" % address_n0)

            #create transactions with colored coin and with TPC
            if amt == 50:
                spend_101_raw = self.nodes[0].createrawtransaction([{"txid": color_txid, "vout": 1}, {"txid": coinbase_txids[height], "vout": 0}], [{address_n1: amt}, {node0_address: 49.99}])
                spend_101_raw = self.nodes[0].signrawtransactionwithwallet(spend_101_raw, [], "ALL", self.options.scheme)["hex"]

                spend_102_raw = self.nodes[0].createrawtransaction([{"txid": color_txid, "vout": 2}, {"txid": coinbase_txids[height+1], "vout": 0}], [{address_n0: amt}, {node0_address: 49.99}])
                spend_102_raw = self.nodes[0].signrawtransactionwithwallet(spend_102_raw, [], "ALL", self.options.scheme)["hex"]

                spend_103_raw = self.nodes[0].createrawtransaction([{"txid": color_txid, "vout": 3}, {"txid": coinbase_txids[height+2], "vout": 0}], [{address_n0: amt}, {node0_address: 49.99}])
                spend_103_raw = self.nodes[0].signrawtransactionwithwallet(spend_103_raw, [], "ALL", self.options.scheme)["hex"]

                # Create a transaction which is time-locked to two blocks in the future
                timelock_tx = self.nodes[0].createrawtransaction([{"txid": color_txid, "vout": 0}, {"txid": coinbase_txids[height+3], "vout": 0}], [{address_n0: amt}, {node0_address: 49.99}])
            else:
                spend_101_raw = create_raw_transaction(self.nodes[0], coinbase_txids[height+1], address_n1, amount=amt)
                spend_102_raw = create_raw_transaction(self.nodes[0], coinbase_txids[height+2], address_n0, amount=amt)
                spend_103_raw = create_raw_transaction(self.nodes[0], coinbase_txids[height+3], address_n0, amount=amt)
                # Create a transaction which is time-locked to two blocks in the future
                timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[height], "vout": 0}], {address_n0: amt})

            # Set the time lock
            timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1)
            timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000"
            timelock_tx = self.nodes[0].signrawtransactionwithwallet(timelock_tx, [], "ALL", self.options.scheme)["hex"]
            # This will raise an exception because the timelock transaction is too immature to spend
            assert_raises_rpc_error(-26, "non-final", self.nodes[0].sendrawtransaction, timelock_tx)

            # Broadcast and mine spend_102 and 103:
            spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw)
            spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw)
            new_blocks =  self.nodes[0].generate(1, self.signblockprivkey_wif)
            # Time-locked transaction is still too immature to spend
            assert_raises_rpc_error(-26, 'non-final', self.nodes[0].sendrawtransaction, timelock_tx)

            # Create 102_1 and 103_1:
            if amt == 50:
                spend_102_1_raw = self.nodes[0].createrawtransaction([{"txid": spend_102_id, "vout": 0}, {"txid": spend_102_id, "vout": 1}], [{address_n1: amt}, {node0_address: 49.98}])
                spend_102_1_raw = self.nodes[0].signrawtransactionwithwallet(spend_102_1_raw, [], "ALL", self.options.scheme)["hex"]

                spend_103_1_raw = self.nodes[0].createrawtransaction([{"txid": spend_103_id, "vout": 0}, {"txid": spend_103_id, "vout": 1}], [{address_n1: amt}, {node0_address: 49.98}])
                spend_103_1_raw = self.nodes[0].signrawtransactionwithwallet(spend_103_1_raw, [], "ALL", self.options.scheme)["hex"]
            else:
                spend_102_1_raw = create_raw_transaction(self.nodes[0], spend_102_id, address_n1, amount=49.98)
                spend_103_1_raw = create_raw_transaction(self.nodes[0], spend_103_id, address_n1, amount=49.98)

            # Broadcast and mine 103_1:
            spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
            last_block = self.nodes[0].generate(1, self.signblockprivkey_wif)
            # Time-locked transaction can now be spent
            timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx)

            # ... now put spend_101 and spend_102_1 in memory pools:
            spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
            spend_102_1_id = self.nodes[0].sendrawtransaction(spend_102_1_raw)

            self.sync_all()

            assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, timelock_tx_id})

            for node in self.nodes:
                node.invalidateblock(last_block[0])
            # Time-locked transaction is now too immature and has been removed from the mempool
            # spend_103_1 has been re-orged out of the chain and is back in the mempool
            assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, spend_103_1_id})

            # Use invalidateblock to re-org back and make all those coinbase spends
            # immature/invalid:
            for node in self.nodes:
                node.invalidateblock(new_blocks[0])

            self.sync_all()

            # mempool should have all trasnactions.
            assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_id, spend_102_1_id, spend_103_id, spend_103_1_id})

            self.nodes[0].generate(1, self.signblockprivkey_wif)

            # finally mempool should be empty
            assert_equal(self.nodes[0].getrawmempool(), [])

            self.log.info("Done")
Exemplo n.º 9
0
    def run_test(self):
        node1 = self.nodes[1]
        node0 = self.nodes[0]
        # Get out of IBD
        node1.generate(1, self.signblockprivkey_wif)
        colorid = create_colored_transaction(2, 500, node1)['color']
        node1.generate(1, self.signblockprivkey_wif)
        [
            node1.sendtoaddress(node0.getnewaddress("", colorid), 10)
            for x in range(3)
        ]
        node1.generate(1, self.signblockprivkey_wif)
        sync_blocks(self.nodes)

        self.nodes[0].add_p2p_connection(TestP2PConn())

        # Test that invs are received for all txs at feerate of 20 sat/byte
        node1.settxfee(Decimal("0.00020000"))
        txids = [
            node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)
        ]
        ctxids = [
            node1.sendtoaddress(node1.getnewaddress("", colorid), 10)
            for x in range(3)
        ]
        assert (allInvsMatch(txids + ctxids, self.nodes[0].p2p))
        self.nodes[0].p2p.clear_invs()

        # Set a filter of 15 sat/byte
        self.nodes[0].p2p.send_and_ping(msg_feefilter(15000))

        # Test that txs are still being received (paying 20 sat/byte)
        txids = [
            node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)
        ]
        ctxids = [
            node1.sendtoaddress(node1.getnewaddress("", colorid), 10)
            for x in range(3)
        ]
        assert (allInvsMatch(txids + ctxids, self.nodes[0].p2p))
        self.nodes[0].p2p.clear_invs()

        # Change tx fee rate to 10 sat/byte and test they are no longer received
        node1.settxfee(Decimal("0.00010000"))
        [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
        [
            node1.sendtoaddress(node1.getnewaddress("", colorid), 10)
            for x in range(3)
        ]
        sync_mempools(self.nodes)  # must be sure node 0 has received all txs

        # Send one transaction from node0 that should be received, so that we
        # we can sync the test on receipt (if node1's txs were relayed, they'd
        # be received by the time this node0 tx is received). This is
        # unfortunately reliant on the current relay behavior where we batch up
        # to 35 entries in an inv, which means that when this next transaction
        # is eligible for relay, the prior transactions from node1 are eligible
        # as well.
        node0.settxfee(Decimal("0.00020000"))
        txids = [node0.sendtoaddress(node0.getnewaddress(), 1)]
        ctxids = [node0.sendtoaddress(node0.getnewaddress("", colorid), 10)]
        assert (allInvsMatch(txids + ctxids, self.nodes[0].p2p))
        self.nodes[0].p2p.clear_invs()

        # Remove fee filter and check that txs are received again
        self.nodes[0].p2p.send_and_ping(msg_feefilter(0))
        txids = [
            node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)
        ]
        ctxids = [
            node1.sendtoaddress(node1.getnewaddress("", colorid), 10)
            for x in range(3)
        ]
        assert (allInvsMatch(txids + ctxids, self.nodes[0].p2p))
        self.nodes[0].p2p.clear_invs()
    def run_test(self):
        colorid = create_colored_transaction(2, 100, self.nodes[0])['color']
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        sync_blocks(self.nodes)
        balance = self.nodes[0].getbalance()
        txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(),
                                          Decimal("10"))
        txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(),
                                          Decimal("10"))
        txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(),
                                          Decimal("10"))
        txD = self.nodes[0].sendtoaddress(
            self.nodes[0].getnewaddress("", colorid), 15)
        self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress("", colorid),
                                    80)
        sync_mempools(self.nodes)
        self.nodes[1].generate(1, self.signblockprivkey_wif)

        # Can not abandon non-wallet transaction
        assert_raises_rpc_error(
            -5, 'Invalid or non-wallet transaction id',
            lambda: self.nodes[0].abandontransaction(txid='ff' * 32))
        # Can not abandon confirmed transaction
        assert_raises_rpc_error(
            -5, 'Transaction not eligible for abandonment',
            lambda: self.nodes[0].abandontransaction(txid=txA))

        sync_blocks(self.nodes)
        newbalance = self.nodes[0].getbalance()
        assert (balance - newbalance < Decimal("0.001")
                )  #no more than fees lost
        balance = newbalance

        # Disconnect nodes so node0's transactions don't get into node1's mempool
        disconnect_nodes(self.nodes[0], 1)

        # Identify the 10tpc outputs
        nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            txA, 1)["vout"]) if vout["value"] == Decimal("10"))
        nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            txB, 1)["vout"]) if vout["value"] == Decimal("10"))
        nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            txC, 1)["vout"]) if vout["value"] == Decimal("10"))
        nD = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            txD, 1)["vout"]) if vout["value"] == 15)

        inputs = []
        # spend 10tpc outputs from txA and txB
        inputs.append({"txid": txA, "vout": nA})
        inputs.append({"txid": txB, "vout": nB})
        outputs = {}

        outputs[self.nodes[0].getnewaddress()] = Decimal("14.99998")
        outputs[self.nodes[1].getnewaddress()] = Decimal("5")
        signed = self.nodes[0].signrawtransactionwithwallet(
            self.nodes[0].createrawtransaction(inputs, outputs), [], "ALL",
            self.options.scheme)
        txAB1 = self.nodes[0].sendrawtransaction(signed["hex"])

        # Identify the 14.99998tpc output
        nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(
            txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998"))

        #Create a child tx spending AB1 and C
        inputs = []
        inputs.append({"txid": txAB1, "vout": nAB})
        inputs.append({"txid": txC, "vout": nC})
        inputs.append({"txid": txD, "vout": nD})
        outputs = {}
        outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996")
        outputs[self.nodes[1].getnewaddress("", colorid)] = 7
        outputs[self.nodes[0].getnewaddress("", colorid)] = 8
        signed2 = self.nodes[0].signrawtransactionwithwallet(
            self.nodes[0].createrawtransaction(inputs, outputs), [], "ALL",
            self.options.scheme)
        txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"])

        # Create a child tx spending ABC2
        signed3_change = Decimal("24.999")
        inputs = [{"txid": txABC2, "vout": 0}, {"txid": txABC2, "vout": 2}]
        outputs = [{
            self.nodes[0].getnewaddress(): signed3_change
        }, {
            self.nodes[0].getnewaddress("", colorid): 2
        }, {
            self.nodes[1].getnewaddress("", colorid): 6
        }]
        signed3 = self.nodes[0].signrawtransactionwithwallet(
            self.nodes[0].createrawtransaction(inputs, outputs), [], "ALL",
            self.options.scheme)
        # note tx is never directly referenced, only abandoned as a child of the above
        self.nodes[0].sendrawtransaction(signed3["hex"])

        # In mempool txs from self should increase balance from change
        newbalance = self.nodes[0].getbalance()
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance'][colorid], 7)
        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(walletinfo['balance'][colorid], 80)
        assert_equal(newbalance, balance - Decimal("30") + signed3_change)
        balance = newbalance

        # Restart the node with a higher min relay fee so the parent tx is no longer in mempool
        # TODO: redo with eviction
        self.stop_node(0)
        self.start_node(0, extra_args=["-minrelaytxfee=0.0001"])

        # Verify txs no longer in either node's mempool
        assert_equal(len(self.nodes[0].getrawmempool()), 0)
        assert_equal(len(self.nodes[1].getrawmempool()), 0)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance'][colorid], 5)
        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(walletinfo['balance'][colorid], 80)

        # Not in mempool txs from self should only reduce balance
        # inputs are still spent, but change not received
        newbalance = self.nodes[0].getbalance()
        assert_equal(newbalance, balance - signed3_change)
        # Unconfirmed received funds that are not in mempool, also shouldn't show
        # up in unconfirmed balance
        unconfbalance = self.nodes[0].getunconfirmedbalance(
        ) + self.nodes[0].getbalance()
        assert_equal(unconfbalance, newbalance)
        # Also shouldn't show up in listunspent
        assert (not txABC2
                in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)])
        balance = newbalance

        # Abandon original transaction and verify inputs are available again
        # including that the child tx was also abandoned
        self.nodes[0].abandontransaction(txAB1)
        newbalance = self.nodes[0].getbalance()
        assert_equal(newbalance, balance + Decimal("30"))
        balance = newbalance

        # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned
        self.stop_node(0)
        self.start_node(0, extra_args=["-minrelaytxfee=0.00001"])
        assert_equal(len(self.nodes[0].getrawmempool()), 0)
        assert_equal(self.nodes[0].getbalance(), balance)

        # But if it is received again then it is unabandoned
        # And since now in mempool, the change is available
        # But its child tx remains abandoned
        self.nodes[0].sendrawtransaction(signed["hex"])
        newbalance = self.nodes[0].getbalance()
        assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998"))
        balance = newbalance

        # Send child tx again so it is unabandoned
        self.nodes[0].sendrawtransaction(signed2["hex"])
        newbalance = self.nodes[0].getbalance()
        assert_equal(
            newbalance,
            balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996"))
        balance = newbalance

        # Remove using high relay fee again
        self.stop_node(0)
        self.start_node(0, extra_args=["-minrelaytxfee=0.0001"])
        assert_equal(len(self.nodes[0].getrawmempool()), 0)
        newbalance = self.nodes[0].getbalance()
        assert_equal(newbalance, balance - Decimal("24.9996"))
        balance = newbalance

        # Create a double spend of AB1 by spending again from only A's 10 output
        # Mine double spend from node 1
        inputs = []
        inputs.append({"txid": txA, "vout": nA})
        outputs = {}
        outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999")
        tx = self.nodes[0].createrawtransaction(inputs, outputs)
        signed = self.nodes[0].signrawtransactionwithwallet(
            tx, [], "ALL", self.options.scheme)
        self.nodes[1].sendrawtransaction(signed["hex"])
        self.nodes[1].generate(1, self.signblockprivkey_wif)

        connect_nodes(self.nodes[0], 1)
        sync_blocks(self.nodes)

        # Verify that B and C's 10 TPC outputs are available for spending again because AB1 is now conflicted
        newbalance = self.nodes[0].getbalance()
        assert_equal(newbalance, balance + Decimal("20"))
        balance = newbalance

        # There is currently a minor bug around this and so this test doesn't work.  See Issue #7315
        # Invalidate the block with the double spend and B's 10 TPC output should no longer be available
        # Don't think C's should either
        self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
        newbalance = self.nodes[0].getbalance()
        #assert_equal(newbalance, balance - Decimal("10"))
        self.log.info(
            "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer"
        )
        self.log.info(
            "conflicted has not resumed causing its inputs to be seen as spent.  See Issue #7315"
        )
        self.log.info(str(balance) + " -> " + str(newbalance) + " ?")
Exemplo n.º 11
0
    def run_test(self):
        self.log.info('prepare some coins for multiple *rawtransaction commands')
        self.nodes[2].generate(1, self.signblockprivkey_wif)
        self.sync_all()
        #generate one block that matures immediately for spending
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        colorid = create_colored_transaction(2, 500, self.nodes[0])['color']
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress("", colorid), 5)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress("", colorid), 10)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress("", colorid), 50)
        self.sync_all()

        self.log.info('Test getrawtransaction on genesis block coinbase returns an error')
        block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
        assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot'])

        self.log.info('Check parameter types and required parameters of createrawtransaction')
        # Test `createrawtransaction` required parameters
        assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction)
        assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [])

        # Test `createrawtransaction` invalid extra parameters
        assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo')

        # Test `createrawtransaction` invalid `inputs`
        txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
        assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {})
        assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {})
        assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{}], {})
        assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
        assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {})
        assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
        assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
        assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {})

        # Test `createrawtransaction` invalid `outputs`
        address = self.nodes[0].getnewaddress()
        address2 = self.nodes[0].getnewaddress()
        caddress = self.nodes[0].getnewaddress("", colorid)
        caddress2 = self.nodes[0].getnewaddress("", colorid)
        assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], 'foo')
        self.nodes[0].createrawtransaction(inputs=[], outputs={})  # Should not throw for backwards compatibility
        self.nodes[0].createrawtransaction(inputs=[], outputs=[])
        assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
        assert_raises_rpc_error(-5, "Invalid Tapyrus address", self.nodes[0].createrawtransaction, [], {'foo': 0})
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {caddress: 'foo'})
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {caddress: '66ae'})
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {caddress: 66.99})
        assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})
        assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {caddress: -1})
        assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
        assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % caddress, self.nodes[0].createrawtransaction, [], multidict([(caddress, 1), (caddress, 1)]))
        assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}])
        assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % caddress, self.nodes[0].createrawtransaction, [], [{caddress: 1}, {caddress: 1}])
        assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}])
        assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']])

        # Test `createrawtransaction` invalid `locktime`
        assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')
        assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1)
        assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296)

        # Test `createrawtransaction` invalid `replaceable`
        assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')

        self.log.info('Check that createrawtransaction accepts an array and object as outputs')
        tx = CTransaction()
        # One output
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={address: 99}))))
        assert_equal(len(tx.vout), 1)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}]),
        )
        # One colored output
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs={caddress: 99}))))
        assert_equal(len(tx.vout), 1)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{caddress: 99}]),
        )
        # Two outputs
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)])))))
        assert_equal(len(tx.vout), 2)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {address2: 99}]),
        )
        # Two colored outputs
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=OrderedDict([(caddress, 99), (caddress2, 99)])))))
        assert_equal(len(tx.vout), 2)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{caddress: 99}, {caddress2: 99}]),
        )
        # Two data outputs
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([('data', '99'), ('data', '99')])))))
        assert_equal(len(tx.vout), 2)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{'data': '99'}, {'data': '99'}]),
        )
        # Multiple mixed outputs
        tx.deserialize(BytesIO(hex_str_to_bytes(self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=multidict([(address, 99), (caddress, 99), ('data', '99'), ('data', '99')])))))
        assert_equal(len(tx.vout), 4)
        assert_equal(
            bytes_to_hex_str(tx.serialize()),
            self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {caddress: 99}, {'data': '99'}, {'data': '99'}]),
        )

        addr = self.nodes[0].getnewaddress("")
        addrinfo = self.nodes[0].getaddressinfo(addr)
        pubkey = addrinfo["scriptPubKey"]

        self.log.info('sendrawtransaction with missing prevtx info')

        # Test `signrawtransactionwithwallet` invalid `prevtxs`
        inputs  = [ {'txid' : txid, 'vout' : 3, 'sequence' : 1000}]
        outputs = { self.nodes[0].getnewaddress() : 1 }
        rawtx   = self.nodes[0].createrawtransaction(inputs, outputs)

        prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1)
        succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx], "ALL", self.options.scheme)
        assert succ["complete"]
        del prevtx["amount"]
        succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx], "ALL", self.options.scheme)
        assert succ["complete"]

        assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [
            {
                "txid": txid,
                "scriptPubKey": pubkey,
                "token": "TPC",
                "amount": 1,
            }
        ], "ALL", self.options.scheme)
        assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [
            {
                "scriptPubKey": pubkey,
                "token": "TPC",
                "vout": 3,
                "amount": 1,
            }
        ], "ALL", self.options.scheme)
        assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [
            {
                "txid": txid,
                "token": "TPC",
                "vout": 3,
                "amount": 1
            }
        ], "ALL", self.options.scheme)

        #########################################
        # sendrawtransaction with missing input #
        #########################################

        self.log.info('sendrawtransaction with missing input')
        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
        outputs = { self.nodes[0].getnewaddress() : 4.998 }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        rawtx   = self.nodes[2].signrawtransactionwithwallet(rawtx, [], "ALL", self.options.scheme)

        # This will raise an exception since there are missing inputs
        assert_raises_rpc_error(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex'])

        #####################################
        # getrawtransaction with block hash #
        #####################################

        # make a tx by sending then generate 2 blocks; block1 has the tx in it
        tx = self.nodes[2].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        block1, block2 = self.nodes[2].generate(2, self.signblockprivkey_wif)
        self.sync_all()
        # We should be able to get the raw transaction by providing the correct block
        gottx = self.nodes[0].getrawtransaction(tx, True, block1)
        assert_equal(gottx['txid'], tx)
        assert_equal(gottx['in_active_chain'], True)
        # We should not have the 'in_active_chain' flag when we don't provide a block
        gottx = self.nodes[0].getrawtransaction(tx, True)
        assert_equal(gottx['txid'], tx)
        assert 'in_active_chain' not in gottx
        # We should not get the tx if we provide an unrelated block
        assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2)
        # An invalid block hash should raise the correct errors
        assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, True)
        assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, "foobar")
        assert_raises_rpc_error(-8, "parameter 3 must be of length 64", self.nodes[0].getrawtransaction, tx, True, "abcd1234")
        assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000")
        # Undo the blocks and check in_active_chain
        self.nodes[0].invalidateblock(block1)
        gottx = self.nodes[0].getrawtransaction(txid=tx, verbose=True, blockhash=block1)
        assert_equal(gottx['in_active_chain'], False)
        self.nodes[0].reconsiderblock(block1)
        assert_equal(self.nodes[0].getbestblockhash(), block2)

        #########################
        # RAW TX MULTISIG TESTS #
        #########################
        # 2of2 test
        addr1 = self.nodes[2].getnewaddress()
        addr2 = self.nodes[2].getnewaddress()

        addr1Obj = self.nodes[2].getaddressinfo(addr1)
        addr2Obj = self.nodes[2].getaddressinfo(addr2)

        # Tests for createmultisig and addmultisigaddress
        assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
        self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
        assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.

        mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']

        #use balance deltas instead of absolute values
        bal = self.nodes[2].getbalance()

        # send 1.2 TPC to msig adr
        txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
        self.sync_all()
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()
        assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance


        # 2of3 test from different nodes
        bal = self.nodes[2].getbalance()
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[2].getnewaddress()
        addr3 = self.nodes[2].getnewaddress()

        addr1Obj = self.nodes[1].getaddressinfo(addr1)
        addr2Obj = self.nodes[2].getaddressinfo(addr2)
        addr3Obj = self.nodes[2].getaddressinfo(addr3)

        mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']

        txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
        decTx = self.nodes[0].gettransaction(txId)
        rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
        self.sync_all()
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        #THIS IS AN INCOMPLETE FEATURE
        #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
        assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable

        txDetails = self.nodes[0].gettransaction(txId, True)
        rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
        vout = False
        for outpoint in rawTx['vout']:
            if outpoint['value'] == Decimal('2.20000000'):
                vout = outpoint
                break

        bal = self.nodes[0].getbalance()
        inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "token": "TPC", "amount" : vout['value']}]
        outputs = { self.nodes[0].getnewaddress() : 2.19 }
        rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
        rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs, "ALL", self.options.scheme)
        assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx

        rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs, "ALL", self.options.scheme)
        assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys
        self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
        rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
        self.sync_all()
        new_block = self.nodes[0].generate(1, self.signblockprivkey_wif)[0]
        self.sync_all()

        #get block reward
        blockData = self.nodes[0].getblock(new_block)
        blockReward = self.nodes[0].gettransaction(blockData['tx'][0])['amount']

        assert_equal(self.nodes[0].getbalance(), bal+blockReward+Decimal('2.19000000')) #block reward + tx

        # 2of2 test for combining transactions
        bal = self.nodes[2].getbalance()
        addr1 = self.nodes[1].getnewaddress()
        addr2 = self.nodes[2].getnewaddress()

        addr1Obj = self.nodes[1].getaddressinfo(addr1)
        addr2Obj = self.nodes[2].getaddressinfo(addr2)

        self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
        mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
        mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)

        txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
        decTx = self.nodes[0].gettransaction(txId)
        rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
        self.sync_all()
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable

        txDetails = self.nodes[0].gettransaction(txId, True)
        rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
        vout = False
        for outpoint in rawTx2['vout']:
            if outpoint['value'] == Decimal('2.20000000'):
                vout = outpoint
                break

        bal = self.nodes[0].getbalance()
        inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "token": "TPC", "amount" : vout['value']}]
        outputs = { self.nodes[0].getnewaddress() : 2.19 }
        rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
        rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs, "ALL", self.options.scheme)
        self.log.debug(rawTxPartialSigned1)
        assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx

        rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs, "ALL", self.options.scheme)
        self.log.debug(rawTxPartialSigned2)
        assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
        rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
        self.log.debug(rawTxComb)
        self.nodes[2].sendrawtransaction(rawTxComb)
        rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
        self.sync_all()
        new_block = self.nodes[0].generate(1, self.signblockprivkey_wif)[0]
        self.sync_all()

        #get block reward
        blockData = self.nodes[0].getblock(new_block)
        blockReward = self.nodes[0].gettransaction(blockData['tx'][0])['amount']

        assert_equal(self.nodes[0].getbalance(), bal+blockReward+Decimal('2.19000000')) #block reward + tx

        # decoderawtransaction tests
        # witness transaction
        encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000"
        assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx)
        # non-witness transaction
        encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
        decrawtx = self.nodes[0].decoderawtransaction(encrawtx)
        assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))

        # getrawtransaction tests
        # 1. valid parameters - only supply txid
        txHash = rawTx["txid"]
        assert_equal(self.nodes[0].getrawtransaction(txHash), rawTxSigned['hex'])

        # 2. valid parameters - supply txid and 0 for non-verbose
        assert_equal(self.nodes[0].getrawtransaction(txHash, 0), rawTxSigned['hex'])

        # 3. valid parameters - supply txid and False for non-verbose
        assert_equal(self.nodes[0].getrawtransaction(txHash, False), rawTxSigned['hex'])

        # 4. valid parameters - supply txid and 1 for verbose.
        # We only check the "hex" field of the output so we don't need to update this test every time the output format changes.
        assert_equal(self.nodes[0].getrawtransaction(txHash, 1)["hex"], rawTxSigned['hex'])

        # 5. valid parameters - supply txid and True for non-verbose
        assert_equal(self.nodes[0].getrawtransaction(txHash, True)["hex"], rawTxSigned['hex'])

        # 6. invalid parameters - supply txid and string "Flase"
        assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, "Flase")

        # 7. invalid parameters - supply txid and empty array
        assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, [])

        # 8. invalid parameters - supply txid and empty dict
        assert_raises_rpc_error(-1, "not a boolean", self.nodes[0].getrawtransaction, txHash, {})

        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 1000}]
        outputs = { self.nodes[0].getnewaddress() : 1 }
        rawtx   = self.nodes[0].createrawtransaction(inputs, outputs)
        decrawtx= self.nodes[0].decoderawtransaction(rawtx)
        assert_equal(decrawtx['vin'][0]['sequence'], 1000)

        # 9. invalid parameters - sequence number out of range
        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}]
        outputs = { self.nodes[0].getnewaddress() : 1 }
        assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)

        # 10. invalid parameters - sequence number out of range
        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}]
        outputs = { self.nodes[0].getnewaddress() : 1 }
        assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range', self.nodes[0].createrawtransaction, inputs, outputs)

        inputs  = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}]
        outputs = { self.nodes[0].getnewaddress() : 1 }
        rawtx   = self.nodes[0].createrawtransaction(inputs, outputs)
        decrawtx= self.nodes[0].decoderawtransaction(rawtx)
        assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)

        ####################################
        # TRANSACTION FEATURES NUMBER TESTS #
        ####################################

        # Test the minimum transaction feature number that fits in a signed 32-bit integer.
        tx = CTransaction()
        tx.nFeatures = -0x80000000
        rawtx = ToHex(tx)
        decrawtx = self.nodes[0].decoderawtransaction(rawtx)
        assert_equal(decrawtx['features'], -0x80000000)

        # Test the maximum transaction feature number that fits in a signed 32-bit integer.
        tx = CTransaction()
        tx.nFeatures = 0x7fffffff
        rawtx = ToHex(tx)
        decrawtx = self.nodes[0].decoderawtransaction(rawtx)
        assert_equal(decrawtx['features'], 0x7fffffff)
Exemplo n.º 12
0
    def run_test(self):
        # Check that there's no UTXO on none of the nodes
        assert_equal(len(self.nodes[0].listunspent()), 0)
        assert_equal(len(self.nodes[1].listunspent()), 0)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("Mining blocks...")

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        out = create_colored_transaction(2, 100, self.nodes[0])
        colorid1 = out['color']
        ctxid = out['txid']
        self.nodes[0].generate(1, self.signblockprivkey_wif)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance']['TPC'], 100)
        assert_equal(walletinfo['balance'][colorid1], 100)

        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])

        assert_equal(self.nodes[0].getbalance(), 100)
        assert_equal(math.floor(self.nodes[1].getbalance()), 50)
        assert_equal(self.nodes[2].getbalance(), 0)

        # Check that only first and second nodes have UTXOs
        utxos = self.nodes[0].listunspent()
        assert_equal(len(utxos), 3)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("test gettxout")
        utxo = [utxo for utxo in utxos if utxo["amount"] >= 50 and utxo["token"] == 'TPC']
        confirmed_txid, confirmed_index = utxo[0]["txid"], utxo[0]["vout"]
        # First, outputs that are unspent both in the chain and in the
        # mempool should appear with or without include_mempool
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=False)
        assert_equal(math.floor(txout['value']), 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(math.floor(txout['value']), 50)

        # Send 21 TPC from 0 to 2 using sendtoaddress call.
        # Locked memory should use at least 32 bytes to sign each transaction
        self.log.info("test getmemoryinfo")
        memory_before = self.nodes[0].getmemoryinfo()
        mempool_txid1 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid2 = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
        memory_after = self.nodes[0].getmemoryinfo()
        assert(memory_before['locked']['used'] + 64 <= memory_after['locked']['used'])

        self.log.info("test gettxout (second part)")
        # utxo spent in mempool should be visible if you exclude mempool
        # but invisible if you include mempool
        txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False)
        assert_equal(math.floor(txout['value']), 50)
        txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True)
        assert txout is None
        # new utxo from mempool should be invisible if you exclude mempool
        # but visible if you include mempool
        txout = self.nodes[0].gettxout(mempool_txid1, 0, False)
        assert txout is None
        txout = self.nodes[0].gettxout(mempool_txid2, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid1, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid1, 1, True)
        txout3 = self.nodes[0].gettxout(mempool_txid2, 0, True)
        txout4 = self.nodes[0].gettxout(mempool_txid2, 1, True)
        # note the mempool tx will have randomly assigned indices
        # but 10 will go to node2 and the rest will go to node0
        balance = self.nodes[0].getbalance()
        assert_equal([txout1['value'] + txout2['value'] + txout3['value'] + txout4['value']], [Decimal('10') + Decimal('11') + balance])
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['balance']['TPC'], balance)
        assert_equal(walletinfo['balance'][colorid1], 100)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])

        # Exercise locking of unspent outputs
        unspent_0 = self.nodes[2].listunspent()[0]
        unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
        assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", self.nodes[2].lockunspent, True, [unspent_0])
        self.nodes[2].lockunspent(False, [unspent_0])
        assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
        assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
        assert_equal([unspent_0], self.nodes[2].listlockunspent())
        self.nodes[2].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[2].listlockunspent()), 0)
        assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
                                self.nodes[2].lockunspent, False,
                                [{"txid": unspent_0["txid"], "vout": 999}])

        # An output should be unlocked when spent
        unspent_0 = self.nodes[1].listunspent()[0]
        self.nodes[1].lockunspent(False, [unspent_0])
        tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
        tx = self.nodes[1].fundrawtransaction(tx)['hex']
        tx = self.nodes[1].signrawtransactionwithwallet(tx, [], "ALL", self.options.scheme)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

        # Have node1 generate 1 block (so node0 can recover the fee)
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])

        # node0 should end up with 100 TPC in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 150 - 21)
        assert_equal(self.nodes[2].getbalance(), 21)

        # Node0 should have two unspent outputs.
        # Create a couple of transactions to send them to node2, submit them through
        # node1, and make sure both node0 and node2 pick them up properly:
        node0utxos = self.nodes[0].listunspent(1)
        assert_equal(len(node0utxos), 4)

        # create both transactions
        txns_to_send = []
        spend_i = 0
        for i, utxo in enumerate(node0utxos):
            if utxo['token'] != 'TPC':
                continue
            spend_i = i
            inputs = []
            outputs = {}
            inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
            outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx, [], "ALL", self.options.scheme))

        # Have node 1 (miner) send the transactions
        self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"], True)
        self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"], True)
        self.nodes[1].sendrawtransaction(txns_to_send[2]["hex"], True)

        # Have node1 mine a block to confirm transactions:
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 141)

        # Verify that a spent output cannot be locked anymore
        spent_itx = {"txid": node0utxos[spend_i]["txid"], "vout": node0utxos[spend_i]["vout"]}
        assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", self.nodes[0].lockunspent, False, [spent_itx])

        # Send 10 TPC normal
        address = self.nodes[0].getnewaddress("test")
        fee_per_byte = Decimal('0.001') / 1000
        self.nodes[2].settxfee(fee_per_byte * 1000)
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
        # generate block on another node so that balance is not distorted by block reward
        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(1, self.signblockprivkey_wif)[0]
        self.sync_all([self.nodes[0:3]])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('131'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 TPC with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        # generate block on another node so that balance is not distorted by block reward
        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))

        # Sendmany 10 TPC
        txid = self.nodes[2].sendmany({address: 10}, "", [])
        # generate block on another node so that balance is not distorted by block reward
        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        node_0_bal += Decimal('10')
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 TPC with subtract fee from amount
        txid = self.nodes[2].sendmany({address: 10}, "", [address])
        # generate block on another node so that balance is not distorted by block reward
        self.sync_all([self.nodes[0:3]])
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))

        # Test ResendWalletTransactions:
        # Create a couple of transactions, then start up a fourth
        # node (nodes[3]) and ask nodes[0] to rebroadcast.
        # EXPECT: nodes[3] should have those transactions in its mempool.
        txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        sync_mempools(self.nodes[0:2])

        self.stop_nodes()
        self.start_node(3, extra_args = ['-acceptnonstdtxn=1'])
        self.start_node(2, extra_args = ['-acceptnonstdtxn=1'])
        self.start_node(1, extra_args = ['-acceptnonstdtxn=1'])
        self.start_node(0, extra_args = ['-acceptnonstdtxn=1'])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        connect_nodes_bi(self.nodes, 0, 3)
        sync_blocks(self.nodes)

        relayed = self.nodes[0].resendwallettransactions()
        assert_equal(set(relayed), {txid1, txid2})
        sync_mempools(self.nodes)

        assert(txid1 in self.nodes[3].getrawmempool())

        # Exercise balance rpcs
        assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"]['TPC'], 1)
        assert_equal(self.nodes[0].getunconfirmedbalance(), 1)

        # check if we can list zero value tx as available coins
        # 1. create raw_tx
        # 2. hex-changed one output to 0.0
        # 3. sign and send
        # 4. check if recipient (node0) can list the zero value tx
        usp = self.nodes[1].listunspent(query_options={'minimumAmount': '49.998'})[0]
        inputs = [{"txid": usp['txid'], "vout": usp['vout']}]
        outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}

        raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000")  # replace 11.11 with 0.0 (int32)
        signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx, [], "ALL", self.options.scheme)
        decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
        zero_value_txid = decoded_raw_tx['txid']
        self.nodes[1].sendrawtransaction(signed_raw_tx['hex'], True)

        self.sync_all()
        self.nodes[1].generate(1, self.signblockprivkey_wif)  # mine a block
        self.sync_all()

        unspent_txs = self.nodes[0].listunspent()  # zero value tx must be in listunspents output
        found = False
        for uTx in unspent_txs:
            if uTx['txid'] == zero_value_txid:
                found = True
                assert_equal(uTx['amount'], Decimal('0'))
        assert(found)

        # do some -walletbroadcast tests
        self.stop_nodes()
        self.start_node(0, ["-walletbroadcast=0"])
        self.start_node(1, ["-walletbroadcast=0"])
        self.start_node(2, ["-walletbroadcast=0"])
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        self.sync_all([self.nodes[0:3]])

        txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
        tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
        self.nodes[1].generate(1, self.signblockprivkey_wif)  # mine a block, tx should not be in there
        self.sync_all([self.nodes[0:3]])
        assert_equal(self.nodes[2].getbalance(), node_2_bal)  # should not be changed because tx was not broadcasted

        # now broadcast from another node, mine a block, sync, and check the balance
        self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
        self.nodes[1].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        node_2_bal += 2
        tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)

        # create another tx
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)

        # restart the nodes with -walletbroadcast=1
        self.stop_nodes()
        self.start_node(0)
        self.start_node(1)
        self.start_node(2)
        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        connect_nodes_bi(self.nodes, 0, 2)
        sync_blocks(self.nodes[0:3])

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        sync_blocks(self.nodes[0:3])
        node_2_bal += 2

        # tx should be added to balance because after restarting the nodes tx should be broadcast
        assert_equal(self.nodes[2].getbalance(), node_2_bal)

        # send a tx with value in a string (PR#6380 +)
        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-2'))

        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-0.0001'))

        # check if JSON parser can handle scientific notation in strings
        txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
        tx_obj = self.nodes[0].gettransaction(txid)
        assert_equal(tx_obj['amount'], Decimal('-0.0001'))

        # This will raise an exception because the amount type is wrong
        assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")

        # This will raise an exception since generate does not accept a string
        assert_raises_rpc_error(-1, "not an integer", self.nodes[0].generate, "2", self.signblockprivkey)

        # Import address and private key to check correct behavior of spendable unspents
        # 1. Send some coins to generate new UTXO
        address_to_import = self.nodes[2].getnewaddress()
        txid = self.nodes[0].sendtoaddress(address_to_import, 1)
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])

        # 2. Import address from node2 to node1
        self.nodes[1].importaddress(address_to_import)

        # 3. Validate that the imported address is watch-only on node1
        assert(self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"])

        # 4. Check that the unspents after import are not spendable
        assert_array_result(self.nodes[1].listunspent(),
                            {"address": address_to_import},
                            {"spendable": False})

        # 5. Import private key of the previously imported address on node1
        priv_key = self.nodes[2].dumpprivkey(address_to_import)
        self.nodes[1].importprivkey(priv_key)

        # 6. Check that the unspents are now spendable on node1
        assert_array_result(self.nodes[1].listunspent(),
                            {"address": address_to_import},
                            {"spendable": True})

        # Mine a block from node0 to an address from node1
        coinbase_addr = self.nodes[1].getnewaddress()
        block_hash = self.nodes[0].generatetoaddress(1, coinbase_addr, self.signblockprivkey_wif)[0]
        coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
        self.sync_all([self.nodes[0:3]])

        # Check that the txid and balance is found by node1
        self.nodes[1].gettransaction(coinbase_txid)

        # check if wallet or blockchain maintenance changes the balance
        self.sync_all([self.nodes[0:3]])
        blocks = self.nodes[0].generate(2, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
        block_count = self.nodes[0].getblockcount()

        # Check modes:
        #   - True: unicode escaped as \u....
        #   - False: unicode directly as UTF-8
        for mode in [True, False]:
            self.nodes[0].rpc.ensure_ascii = mode
            # unicode check: Basic Multilingual Plane, Supplementary Plane respectively
            for label in [u'б€б‹аБаА', u'№…Ё']:
                addr = self.nodes[0].getnewaddress()
                self.nodes[0].setlabel(addr, label)
                assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label)
                assert(label in self.nodes[0].listlabels())
        self.nodes[0].rpc.ensure_ascii = True  # restore to default

        # maintenance tests
        maintenance = [
            '-rescan',
            '-reindex',
            '-zapwallettxes=1',
            '-zapwallettxes=2',
            # disabled until issue is fixed: https://github.com/bitcoin/bitcoin/issues/7463
            # '-salvagewallet',
        ]
        chainlimit = 6
        for m in maintenance:
            self.log.info("check " + m)
            self.stop_nodes()
            # set lower ancestor limit for later
            self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
            self.start_node(1, [m, "-limitancestorcount=" + str(chainlimit)])
            self.start_node(2, [m, "-limitancestorcount=" + str(chainlimit)])
            if m == '-reindex':
                # reindex will leave rpc warm up "early"; Wait for it to finish
                wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
            assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])

        # Exercise listsinceblock with the last two blocks
        coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0])
        assert_equal(coinbase_tx_1["lastblock"], blocks[1])
        assert_equal(len(coinbase_tx_1["transactions"]), 1)
        assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1])
        assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0)

        # ==Check that wallet prefers to use coins that don't exceed mempool limits =====

        # Get all non-zero utxos together
        chain_addrs = [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()]
        singletxid = self.nodes[0].sendtoaddress(chain_addrs[0], self.nodes[0].getbalance(), "", "", True)
        node0_balance = self.nodes[0].getbalance()
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        # Split into two chains
        rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
        signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx, [], "ALL", self.options.scheme)
        singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1, self.signblockprivkey_wif)

        # Make a long chain of unconfirmed payments without hitting mempool limit
        # Each tx we make leaves only one output of change on a chain 1 longer
        # Since the amount to send is always much less than the outputs, we only ever need one output
        # So we should be able to generate exactly chainlimit txs for each original output
        sending_addr = self.nodes[1].getnewaddress()
        txid_list = []
        for i in range(chainlimit * 4): #including 2 block rewards its 4
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 4)
        assert_equal(len(txid_list), chainlimit * 4)

        # Without walletrejectlongchains, we will still generate a txid
        # The tx will be stored in the wallet but not accepted to the mempool
        extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001'))
        assert(extra_txid not in self.nodes[0].getrawmempool())
        assert(extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()])
        self.nodes[0].abandontransaction(extra_txid)
        total_txs = len(self.nodes[0].listtransactions(99999))

        # Try with walletrejectlongchains
        # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
        self.stop_node(0)
        self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])

        # wait for loadmempool
        timeout = 10
        while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 4):
            time.sleep(0.5)
            timeout -= 0.5
        assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 4)

        node0_balance = self.nodes[0].getbalance()
        # With walletrejectlongchains we will not create the tx and store it in our wallet.
        assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))

        # Verify nothing new in wallet
        assert_equal(total_txs, len(self.nodes[0].listtransactions(99999)))

        # Test getaddressinfo. Note that these addresses are taken from disablewallet.py
        assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
        address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
        assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
        assert_equal(address_info["scriptPubKey"], "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac")
        assert not address_info["ismine"]
        assert not address_info["iswatchonly"]
        assert not address_info["isscript"]
Exemplo n.º 13
0
    def run_test(self):
        # Mine some coins
        self.nodes[0].generate(5, self.signblockprivkey_wif)
        colorid1 = create_colored_transaction(2, 100, self.nodes[0])['color']
        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        # Get some addresses from the two nodes
        addr1 = [self.nodes[1].getnewaddress() for i in range(3)]
        addr2 = [self.nodes[2].getnewaddress() for i in range(3)]
        addrs = addr1 + addr2

        caddr1 = [self.nodes[1].getnewaddress("", colorid1) for i in range(3)]
        caddr2 = [self.nodes[2].getnewaddress("", colorid1) for i in range(3)]
        caddrs = caddr1 + caddr2

        # Send 1 + 0.5 coin to each address
        [self.nodes[0].sendtoaddress(addr, 1.0) for addr in addrs]
        [self.nodes[0].sendtoaddress(addr, 0.5) for addr in addrs]

        [self.nodes[0].sendtoaddress(caddr, 1) for caddr in caddrs]
        [self.nodes[0].sendtoaddress(caddr, 2) for caddr in caddrs]

        self.nodes[0].generate(1, self.signblockprivkey_wif)
        self.sync_all()

        # For each node, send 0.2 coins back to 0;
        # - node[1] should pick one 0.5 UTXO and leave the rest
        # - node[2] should pick one (1.0 + 0.5) UTXO group corresponding to a
        #   given address, and leave the rest
        txid1 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        tx1 = self.nodes[1].getrawtransaction(txid1, True)
        # txid1 should have 1 input and 2 outputs
        assert_equal(1, len(tx1["vin"]))
        assert_equal(2, len(tx1["vout"]))
        # one output should be 0.2, the other should be ~0.3
        v = [vout["value"] for vout in tx1["vout"]]
        v.sort()
        assert_approx(v[0], 0.2)
        assert_approx(v[1], 0.3, 0.0001)

        ctxid1 = self.nodes[1].sendtoaddress(
            self.nodes[0].getnewaddress("", colorid1), 2)
        ctx1 = self.nodes[1].getrawtransaction(ctxid1, True)
        # txid1 should have 2 input and 2 outputs
        assert_equal(2, len(ctx1["vin"]))
        assert_equal(2, len(ctx1["vout"]))
        # one output should be 2, the other should be fee
        v = [vout["value"] for vout in ctx1["vout"]]
        v.sort()
        assert_approx(v[0], 0.5, 0.0001)
        assert_approx(v[1], 2)

        txid2 = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        tx2 = self.nodes[2].getrawtransaction(txid2, True)
        # txid2 should have 2 inputs and 2 outputs
        assert_equal(2, len(tx2["vin"]))
        assert_equal(2, len(tx2["vout"]))
        # one output should be 0.2, the other should be ~1.3
        v = [vout["value"] for vout in tx2["vout"]]
        v.sort()
        assert_approx(v[0], 0.2)
        assert_approx(v[1], 1.3, 0.0001)

        ctxid2 = self.nodes[2].sendtoaddress(
            self.nodes[0].getnewaddress("", colorid1), 2)
        ctx2 = self.nodes[2].getrawtransaction(ctxid2, True)
        # txid2 should have 4 inputs and 3 outputs
        assert_equal(4, len(ctx2["vin"]))
        assert_equal(3, len(ctx2["vout"]))
        # one output should be 2, the other should be fee
        v = [vout["value"] for vout in ctx2["vout"]]
        v.sort()
        assert_approx(v[0], 1)
        assert_approx(v[1], 1.5, 0.0002)
        assert_approx(v[2], 2)

        # Empty out node2's wallet
        self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(),
                                    amount=self.nodes[2].getbalance(),
                                    subtractfeefromamount=True)
        self.sync_all()
        self.nodes[2].generate(1, self.signblockprivkey_wif)

        amt = self.nodes[2].getwalletinfo()['balance'][colorid1]
        self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(
            "", colorid1),
                                    amount=amt)
        self.sync_all()
        self.nodes[0].generate(1, self.signblockprivkey_wif)

        # Fill node2's wallet with 10000 outputs corresponding to the same
        # scriptPubKey
        for i in range(5):
            raw_tx = self.nodes[0].createrawtransaction([{
                "txid": "0" * 64,
                "vout": 0
            }], [{
                addr2[0]: 0.05
            }])
            tx = FromHex(CTransaction(), raw_tx)
            tx.vin = []
            tx.vout = [tx.vout[0]] * 2000
            funded_tx = self.nodes[0].fundrawtransaction(ToHex(tx))
            signed_tx = self.nodes[0].signrawtransactionwithwallet(
                funded_tx['hex'], [], "ALL", self.options.scheme)
            self.nodes[0].sendrawtransaction(signed_tx['hex'])
            self.nodes[0].generate(1, self.signblockprivkey_wif)

        self.sync_all()

        # Check that we can create a transaction that only requires ~100 of our
        # utxos, without pulling in all outputs and creating a transaction that
        # is way too big.
        assert self.nodes[2].sendtoaddress(address=addr2[0], amount=5)