def test_no_blockhash(self):
        txid = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1)
        blockhash, = self.nodes[2].generate(1)
        self.sync_all()

        txs = self.nodes[0].listtransactions()
        assert_array_result(txs, {"txid": txid}, {
            "category": "receive",
            "amount": 1,
            "blockhash": blockhash,
            "confirmations": 1,
        })
        assert_equal(
            self.nodes[0].listsinceblock(),
            {"lastblock": blockhash,
             "removed": [],
             "transactions": txs})
        assert_equal(
            self.nodes[0].listsinceblock(""),
            {"lastblock": blockhash,
             "removed": [],
             "transactions": txs})
 def assert_category(self, category, address, txid, skip):
     assert_array_result(self.nodes[0].listtransactions(skip=skip),
                         {"address": address},
                         {"category": category})
     assert_array_result(self.nodes[0].listsinceblock()["transactions"],
                         {"address": address},
                         {"category": category})
     assert_array_result(self.nodes[0].gettransaction(txid)["details"],
                         {"address": address},
                         {"category": category})
    def run_test(self):
        self.nodes[0].generate(1)  # Get out of IBD
        self.sync_all()
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0})
        # mine a block, confirmations should change:
        self.nodes[0].generate(1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-0.1"), "confirmations": 1})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal("0.1"), "confirmations": 1})

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "send"},
                            {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "receive"},
                            {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {self.nodes[0].getnewaddress(): 0.11,
                   self.nodes[1].getnewaddress(): 0.22,
                   self.nodes[0].getnewaddress(): 0.33,
                   self.nodes[1].getnewaddress(): 0.44}
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-0.11")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal("0.11")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-0.22")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal("0.22")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-0.33")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal("0.33")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-0.44")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal("0.44")},
                            {"txid": txid})

        pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
        multisig = self.nodes[1].createmultisig(1, [pubkey])
        self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
        self.nodes[1].generate(1)
        self.sync_all()
        assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
        assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
                            {"category": "receive", "amount": Decimal("0.1")},
                            {"txid": txid, "label": "watchonly"})

        self.run_rbf_opt_in_test()
    def run_test(self):
        # Generate block to get out of IBD
        self.nodes[0].generate(1)

        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.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr}, {
                                "address": addr,
                                "label": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        # With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr}, {
                                "address": addr,
                                "label": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        # With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11),
                            {"address": addr}, {}, True)

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

        #Test Address filtering
        #Only on addr
        expected = {
            "address": addr,
            "label": "",
            "amount": Decimal("0.1"),
            "confirmations": 10,
            "txids": [
                txid,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(minconf=0,
                                                  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,
                                minconf=0,
                                include_empty=True,
                                include_watchonly=True,
                                address_filter="bamboozling")
        #Another address receive money
        res = self.nodes[1].listreceivedbyaddress(0, 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.sync_all()
        #Same test as above should still pass
        expected = {
            "address": addr,
            "label": "",
            "amount": Decimal("0.1"),
            "confirmations": 11,
            "txids": [
                txid,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(0, 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": "",
            "amount": Decimal("0.1"),
            "confirmations": 1,
            "txids": [
                txid2,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(0, 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(0, 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(0, 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].getreceivedbyaddress(addr, 0)
        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.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
        addrArr = self.nodes[1].getnewaddress()
        label = self.nodes[1].getaccount(addrArr)
        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.sync_all()
        # listreceivedbylabel should return updated received list
        assert_array_result(
            self.nodes[1].listreceivedbylabel(), {"label": label}, {
                "label": received_by_label_json["label"],
                "amount": (received_by_label_json["amount"] + Decimal("0.1"))
            })

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

        # Create a new label named "mynewlabel" that has a 0 balance
        self.nodes[1].getlabeladdress(label="mynewlabel", force=True)
        received_by_label_json = [
            r for r in self.nodes[1].listreceivedbylabel(0, 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, Decimal("0.0"))
Beispiel #5
0
    def run_test(self):
        # Generate block to get out of IBD
        self.nodes[0].generate(1)
        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.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr},
                            {"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr},
                            {"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True)

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

        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].getreceivedbyaddress(addr, 0)
        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.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("listreceivedbyaccount + getreceivedbyaccount Test")

        # set pre-state
        addrArr = self.nodes[1].getnewaddress()
        account = self.nodes[1].getaccount(addrArr)
        received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount() if r["account"] == account][0]
        balance_by_account = self.nodes[1].getreceivedbyaccount(account)

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

        # listreceivedbyaccount should return received_by_account_json because of 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbyaccount(),
                            {"account": account},
                            received_by_account_json)

        # getreceivedbyaddress should return same balance because of 0 confirmations
        balance = self.nodes[1].getreceivedbyaccount(account)
        assert_equal(balance, balance_by_account)

        self.nodes[1].generate(10)
        self.sync_all()
        # listreceivedbyaccount should return updated account balance
        assert_array_result(self.nodes[1].listreceivedbyaccount(),
                            {"account": account},
                            {"account": received_by_account_json["account"], "amount": (received_by_account_json["amount"] + Decimal("0.1"))})

        # getreceivedbyaddress should return updates balance
        balance = self.nodes[1].getreceivedbyaccount(account)
        assert_equal(balance, balance_by_account + Decimal("0.1"))

        # Create a new account named "mynewaccount" that has a 0 balance
        self.nodes[1].getaccountaddress("mynewaccount")
        received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount(0, True) if r["account"] == "mynewaccount"][0]

        # Test includeempty of listreceivedbyaccount
        assert_equal(received_by_account_json["amount"], Decimal("0.0"))

        # Test getreceivedbyaccount for 0 amount accounts
        balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
        assert_equal(balance, Decimal("0.0"))
Beispiel #6
0
    def run_rbf_opt_in_test(self):
        # Check whether a transaction signals opt-in RBF itself
        def is_opt_in(node, txid):
            rawtx = node.getrawtransaction(txid, 1)
            for x in rawtx["vin"]:
                if x["sequence"] < 0xfffffffe:
                    return True
            return False

        # Find an unconfirmed output matching a certain txid
        def get_unconfirmed_utxo_entry(node, txid_to_match):
            utxo = node.listunspent(0, 0)
            for i in utxo:
                if i["txid"] == txid_to_match:
                    return i
            return None

        # 1. Chain a few transactions that don't opt-in.
        txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        assert (not is_opt_in(self.nodes[0], txid_1))
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1},
                            {"bip125-replaceable": "no"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1},
                            {"bip125-replaceable": "no"})

        # Tx2 will build off txid_1, still not opting in to RBF.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1)
        assert_equal(utxo_to_use["safe"], True)
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
        assert_equal(utxo_to_use["safe"], False)

        # Create tx2 using createrawtransaction
        inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.999}
        tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
        txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)

        # ...and check the result
        assert (not is_opt_in(self.nodes[1], txid_2))
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2},
                            {"bip125-replaceable": "no"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2},
                            {"bip125-replaceable": "no"})

        # Tx3 will opt-in to RBF
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
        inputs = [{"txid": txid_2, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[1].getnewaddress(): 0.998}
        tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
        tx3_modified = tx_from_hex(tx3)
        tx3_modified.vin[0].nSequence = 0
        tx3 = bytes_to_hex_str(tx3_modified.serialize())
        tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex']
        txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)

        assert (is_opt_in(self.nodes[0], txid_3))
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3},
                            {"bip125-replaceable": "yes"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3},
                            {"bip125-replaceable": "yes"})

        # Tx4 will chain off tx3.  Doesn't signal itself, but depends on one
        # that does.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
        inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.997}
        tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
        txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)

        assert (not is_opt_in(self.nodes[1], txid_4))
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "yes"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "yes"})

        # Replace tx3, and check that tx4 becomes unknown
        tx3_b = tx3_modified
        tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN)  # bump the fee
        tx3_b = bytes_to_hex_str(tx3_b.serialize())
        tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex']
        txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
        assert (is_opt_in(self.nodes[0], txid_3b))

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "unknown"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "unknown"})

        # Check gettransaction as well:
        for n in self.nodes[0:2]:
            assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
            assert_equal(
                n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
            assert_equal(
                n.gettransaction(txid_4)["bip125-replaceable"], "unknown")

        # After mining a transaction, it's no longer BIP125-replaceable
        self.nodes[0].generate(1)
        assert (txid_3b not in self.nodes[0].getrawmempool())
        assert_equal(
            self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
        assert_equal(
            self.nodes[0].gettransaction(txid_4)["bip125-replaceable"],
            "unknown")
Beispiel #7
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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 50)
        assert_equal(walletinfo['balance'], 0)

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

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[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(txout['value'], 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 50)

        # Send 21 BPS from 0 to 2 using sendtoaddress call.
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)

        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(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_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 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(set([txout1['value'], txout2['value']]), set([10, balance]))
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        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(-6, "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, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "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}])

        # The lock on a manually selected output is ignored
        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 })
        self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})

        # fundrawtransaction can lock an input
        self.nodes[1].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[1].listlockunspent()), 0)
        tx = self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})['hex']
        assert_equal(len(self.nodes[1].listlockunspent()), 1)

        # Send transaction
        tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

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

        # node0 should end up with 100 BPS in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 100 - 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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            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))

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

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

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

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

        # Send 10 BPS 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)
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 BPS with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))

        # Sendmany 10 BPS
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 BPS with subtract fee from amount
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))

        # Sendmany with explicit fee (BTC/kB)
        # Throw if no conf_target provided
        assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
            self.nodes[2].sendmany,
            amounts={ address: 10 },
            estimate_mode='bTc/kB')
        # Throw if negative feerate
        assert_raises_rpc_error(-3, "Amount out of range",
            self.nodes[2].sendmany,
            amounts={ address: 10 },
            conf_target=-1,
            estimate_mode='bTc/kB')
        fee_per_kb = 0.0002500
        explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
        txid = self.nodes[2].sendmany(
            amounts={ address: 10 },
            conf_target=fee_per_kb,
            estimate_mode='bTc/kB',
        )
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        node_0_bal += Decimal('10')
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany with explicit fee (SAT/B)
        # Throw if no conf_target provided
        assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
            self.nodes[2].sendmany,
            amounts={ address: 10 },
            estimate_mode='sat/b')
        # Throw if negative feerate
        assert_raises_rpc_error(-3, "Amount out of range",
            self.nodes[2].sendmany,
            amounts={ address: 10 },
            conf_target=-1,
            estimate_mode='sat/b')
        fee_sat_per_b = 2
        fee_per_kb = fee_sat_per_b / 100000.0
        explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
        txid = self.nodes[2].sendmany(
            amounts={ address: 10 },
            conf_target=fee_sat_per_b,
            estimate_mode='sAT/b',
        )
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        balance = self.nodes[2].getbalance()
        node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(balance, node_2_bal)
        node_0_bal += Decimal('10')
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        self.start_node(3, self.nodes[3].extra_args)
        connect_nodes(self.nodes[0], 3)
        self.sync_all()

        # 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)
        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'])

        self.sync_all()
        self.nodes[1].generate(1)  # 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(self.nodes[0], 1)
        connect_nodes(self.nodes[1], 2)
        connect_nodes(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)  # 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.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(self.nodes[0], 1)
        connect_nodes(self.nodes[1], 2)
        connect_nodes(self.nodes[0], 2)
        self.sync_blocks(self.nodes[0:3])

        self.nodes[0].generate(1)
        self.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'))

        # General checks for errors from incorrect inputs
        # This will raise an exception because the amount is negative
        assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1")

        # 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")

        if not self.options.descriptors:

            # This will raise an exception for the invalid private key format
            assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")

            # This will raise an exception for importing an address with the PS2H flag
            temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
            assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)

            # This will raise an exception for attempting to dump the private key of an address you do not own
            assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)

            # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].dumpprivkey, "invalid")

            # This will raise an exception for attempting to set a label for an invalid Bitcoin address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].setlabel, "invalid address", "label")

            # This will raise an exception for importing an invalid address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid")

            # This will raise an exception for attempting to import a pubkey that isn't in hex
            assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")

            # This will raise an exception for importing an invalid pubkey
            assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")

            # 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.sync_all(self.nodes[0:3])

            # send with explicit btc/kb fee
            self.log.info("test explicit fee (sendtoaddress as btc/kb)")
            self.nodes[0].generate(1)
            self.sync_all(self.nodes[0:3])
            prebalance = self.nodes[2].getbalance()
            assert prebalance > 2
            address = self.nodes[1].getnewaddress()
            # Throw if no conf_target provided
            assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
                self.nodes[2].sendtoaddress,
                address=address,
                amount=1.0,
                estimate_mode='BTc/Kb')
            # Throw if negative feerate
            assert_raises_rpc_error(-3, "Amount out of range",
                self.nodes[2].sendtoaddress,
                address=address,
                amount=1.0,
                conf_target=-1,
                estimate_mode='btc/kb')
            txid = self.nodes[2].sendtoaddress(
                address=address,
                amount=1.0,
                conf_target=0.00002500,
                estimate_mode='btc/kb',
            )
            tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
            self.sync_all(self.nodes[0:3])
            self.nodes[0].generate(1)
            self.sync_all(self.nodes[0:3])
            postbalance = self.nodes[2].getbalance()
            fee = prebalance - postbalance - Decimal('1')
            assert_fee_amount(fee, tx_size, Decimal('0.00002500'))

            # send with explicit sat/b fee
            self.sync_all(self.nodes[0:3])
            self.log.info("test explicit fee (sendtoaddress as sat/b)")
            self.nodes[0].generate(1)
            prebalance = self.nodes[2].getbalance()
            assert prebalance > 2
            address = self.nodes[1].getnewaddress()
            # Throw if no conf_target provided
            assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
                self.nodes[2].sendtoaddress,
                address=address,
                amount=1.0,
                estimate_mode='SAT/b')
            # Throw if negative feerate
            assert_raises_rpc_error(-3, "Amount out of range",
                self.nodes[2].sendtoaddress,
                address=address,
                amount=1.0,
                conf_target=-1,
                estimate_mode='SAT/b')
            txid = self.nodes[2].sendtoaddress(
                address=address,
                amount=1.0,
                conf_target=2,
                estimate_mode='SAT/B',
            )
            tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
            self.sync_all(self.nodes[0:3])
            self.nodes[0].generate(1)
            self.sync_all(self.nodes[0:3])
            postbalance = self.nodes[2].getbalance()
            fee = prebalance - postbalance - Decimal('1')
            assert_fee_amount(fee, tx_size, Decimal('0.00002000'))

            # 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)[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.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)
                test_address(self.nodes[0], addr, labels=[label])
                assert label in self.nodes[0].listlabels()
        self.nodes[0].rpc.ensure_ascii = True  # restore to default

        # maintenance tests
        maintenance = [
            '-rescan',
            '-reindex',
        ]
        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
                self.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)
        self.nodes[0].generate(1)
        node0_balance = self.nodes[0].getbalance()
        # 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)
        singletxid = self.nodes[0].sendrawtransaction(hexstring=signedtx["hex"], maxfeerate=0)
        self.nodes[0].generate(1)

        # 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 _ in range(chainlimit * 2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
        assert_equal(len(txid_list), chainlimit * 2)

        # 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)
        extra_args = ["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]
        self.start_node(0, extra_args=extra_args)

        # wait until the wallet has submitted all transactions to the mempool
        self.wait_until(lambda: len(self.nodes[0].getrawmempool()) == chainlimit * 2)

        # Prevent potential race condition when calling wallet RPCs right after restart
        self.nodes[0].syncwithvalidationinterfacequeue()

        node0_balance = self.nodes[0].getbalance()
        # With walletrejectlongchains we will not create the tx and store it in our wallet.
        assert_raises_rpc_error(-6, "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 on external address. 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"]
        assert not address_info["ischange"]

        # Test getaddressinfo 'ischange' field on change address.
        self.nodes[0].generate(1)
        destination = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(destination, 0.123)
        tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex'])
        output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
        assert len(output_addresses) > 1
        for address in output_addresses:
            ischange = self.nodes[0].getaddressinfo(address)['ischange']
            assert_equal(ischange, address != destination)
            if ischange:
                change = address
        self.nodes[0].setlabel(change, 'foobar')
        assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)

        # Test gettransaction response with different arguments.
        self.log.info("Testing gettransaction response with different arguments...")
        self.nodes[0].setlabel(change, 'baz')
        baz = self.nodes[0].listtransactions(label="baz", count=1)[0]
        expected_receive_vout = {"label":    "baz",
                                 "address":  baz["address"],
                                 "amount":   baz["amount"],
                                 "category": baz["category"],
                                 "vout":     baz["vout"]}
        expected_fields = frozenset({'amount', 'bip125-replaceable', 'confirmations', 'details', 'fee',
                                     'hex', 'time', 'timereceived', 'trusted', 'txid', 'walletconflicts'})
        verbose_field = "decoded"
        expected_verbose_fields = expected_fields | {verbose_field}

        self.log.debug("Testing gettransaction response without verbose")
        tx = self.nodes[0].gettransaction(txid=txid)
        assert_equal(set([*tx]), expected_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)

        self.log.debug("Testing gettransaction response with verbose set to False")
        tx = self.nodes[0].gettransaction(txid=txid, verbose=False)
        assert_equal(set([*tx]), expected_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)

        self.log.debug("Testing gettransaction response with verbose set to True")
        tx = self.nodes[0].gettransaction(txid=txid, verbose=True)
        assert_equal(set([*tx]), expected_verbose_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)
        assert_equal(tx[verbose_field], self.nodes[0].decoderawtransaction(tx["hex"]))
Beispiel #8
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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 250)
        assert_equal(walletinfo['balance'], 0)

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

        assert_equal(self.nodes[0].getbalance(), 250)
        assert_equal(self.nodes[1].getbalance(), 250)
        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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Exercise locking of unspent outputs
        unspent_0 = self.nodes[1].listunspent()[0]
        unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
        self.nodes[1].lockunspent(False, [unspent_0])
        assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[1].sendtoaddress, self.nodes[1].getnewaddress(), 20)
        assert_equal([unspent_0], self.nodes[1].listlockunspent())
        self.nodes[1].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

        # Send 21 PIV from 1 to 0 using sendtoaddress call.
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 21)
        self.nodes[1].generate(1)
        self.sync_all([self.nodes[0:3]])

        # 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), 2)

        # create both transactions
        fee_per_kbyte = Decimal('0.001')
        txns_to_send = []
        for utxo in node0utxos:
            inputs = []
            outputs = {}
            inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
            outputs[self.nodes[2].getnewaddress()] = float(utxo["amount"]) - float(fee_per_kbyte)
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))

        # 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)

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

        assert_equal(self.nodes[0].getbalance(), 0)
        node_2_expected_bal = Decimal('250') + Decimal('21') - 2 * fee_per_kbyte
        node_2_bal = self.nodes[2].getbalance()
        assert_equal(node_2_bal, node_2_expected_bal)

        # Send 10 PIV normal
        address = self.nodes[0].getnewaddress("test")
        self.nodes[2].settxfee(float(fee_per_kbyte))
        txid = self.nodes[2].sendtoaddress(address, 10, "", "")
        fee = self.nodes[2].gettransaction(txid)["fee"]
        node_2_bal -= (Decimal('10') - fee)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_0_bal = self.nodes[0].getbalance()
        assert_equal(node_0_bal, Decimal('10'))

        # Sendmany 10 PIV
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "")
        fee = self.nodes[2].gettransaction(txid)["fee"]
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_0_bal += Decimal('10')
        node_2_bal -= (Decimal('10') - fee)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        assert_equal(self.nodes[0].getbalance(), node_0_bal)
        assert_fee_amount(-fee, self.get_vsize(self.nodes[2].getrawtransaction(txid)), fee_per_kbyte)

        # 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")

        # 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()
        self.nodes[0].sendtoaddress(address_to_import, 1)
        self.nodes[0].generate(1)
        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].validateaddress(address_to_import)["iswatchonly"])

        # 4. Check that the unspents after import are not spendable
        listunspent = self.nodes[1].listunspent(1, 9999999, [], 2)
        assert_array_result(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})

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

        maintenance = [
            '-rescan',
            '-reindex',
        ]
        for m in maintenance:
            self.log.info("check " + m)
            self.stop_nodes()
            # set lower ancestor limit for later
            self.start_node(0, [m])
            self.start_node(1, [m])
            self.start_node(2, [m])
            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)
Beispiel #9
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)

        walletinfo = self.nodes[0].getwalletinfo()
        self.check_wallet_processed_blocks(0, walletinfo)
        assert_equal(walletinfo['immature_balance'], 250)
        assert_equal(walletinfo['balance'], 0)

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

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

        walletinfo = self.nodes[0].getwalletinfo()
        self.check_wallet_processed_blocks(0, walletinfo)
        self.check_wallet_processed_blocks(1, self.nodes[1].getwalletinfo())
        self.check_wallet_processed_blocks(2, self.nodes[2].getwalletinfo())

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

        assert_equal(walletinfo['immature_balance'], 0)

        # Exercise locking of unspent outputs
        unspent_0 = self.nodes[1].listunspent()[0]
        assert unspent_0["solvable"]
        assert unspent_0["spendable"]
        assert unspent_0["safe"]
        unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
        self.nodes[1].lockunspent(False, [unspent_0])
        assert_raises_rpc_error(-4, "Insufficient funds",
                                self.nodes[1].sendtoaddress,
                                self.nodes[1].getnewaddress(), 20)
        assert_equal([unspent_0], self.nodes[1].listlockunspent())
        self.nodes[1].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

        # Send 21 PIV from 1 to 0 using sendtoaddress call.
        # Locked memory should use at least 32 bytes to sign the transaction
        self.log.info("test getmemoryinfo")
        memory_before = self.nodes[0].getmemoryinfo()
        self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 21)
        memory_after = self.nodes[0].getmemoryinfo()
        assert (memory_before['locked']['used'] + 32 <=
                memory_after['locked']['used'])
        self.sync_mempools(self.nodes[0:3])

        # Node0 should have two unspent outputs.
        # One safe, the other one not yet
        node0utxos = self.nodes[0].listunspent(0)
        assert_equal(len(node0utxos), 2)
        newutxos = [x for x in node0utxos if x["txid"] != utxos[0]["txid"]]
        assert_equal(len(newutxos), 1)
        assert not newutxos[0]["safe"]

        # Mine the other tx
        self.nodes[1].generate(1)
        self.sync_all(self.nodes[0:3])
        node0utxos = self.nodes[0].listunspent()
        assert_equal(len(node0utxos), 2)
        for u in node0utxos:
            assert u["safe"]

        # 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:
        # create both transactions
        fee_per_kbyte = Decimal('0.001')
        txns_to_send = []
        for utxo in node0utxos:
            inputs = []
            outputs = {}
            inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
            outputs[self.nodes[2].getnewaddress()] = float(
                utxo["amount"]) - float(fee_per_kbyte)
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))

        # 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)

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

        assert_equal(self.nodes[0].getbalance(), 0)
        node_2_expected_bal = Decimal('250') + Decimal(
            '21') - 2 * fee_per_kbyte
        node_2_bal = self.nodes[2].getbalance()
        assert_equal(node_2_bal, node_2_expected_bal)

        # Send 10 PIV normal
        self.log.info("test sendtoaddress")
        address = self.nodes[0].getnewaddress("test")
        self.nodes[2].settxfee(float(fee_per_kbyte))
        txid = self.nodes[2].sendtoaddress(address, 10, "", "")
        fee = self.nodes[2].gettransaction(txid)["fee"]  # fee < 0
        node_2_bal -= (Decimal('10') - fee)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        node_0_bal = self.nodes[0].getbalance()
        assert_equal(node_0_bal, Decimal('10'))

        # Sendmany 10 PIV
        self.log.info("test sendmany")
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "")
        fee = self.nodes[2].gettransaction(txid)["fee"]
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        node_0_bal += Decimal('10')
        node_2_bal -= (Decimal('10') - fee)
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        assert_equal(self.nodes[0].getbalance(), node_0_bal)
        assert_fee_amount(
            -fee, self.get_vsize(self.nodes[2].getrawtransaction(txid)),
            fee_per_kbyte)

        # 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()
        self.nodes[0].sendtoaddress(address_to_import, 1)
        self.nodes[0].generate(1)
        self.sync_all(self.nodes[0:3])

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

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

        # 4. Check that the unspents after import are not spendable
        listunspent = self.nodes[1].listunspent(1, 9999999, [], 2)
        assert_array_result(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.log.info("test importprivkey")
        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})

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

        maintenance = [
            '-rescan',
            '-reindex',
        ]
        for m in maintenance:
            self.log.info("check " + m)
            self.stop_nodes()
            # set lower ancestor limit for later
            self.start_node(0, [m])
            self.start_node(1, [m])
            self.start_node(2, [m])
            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
        self.check_wallet_processed_blocks(0, self.nodes[0].getwalletinfo())
        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)

        # Excercise query_options parameter in listunspent
        # Node 1 has:
        # - 1 coin of 1.00 PIV
        # - 7 coins of 250.00 PIV
        # - 1 coin of 228.9999xxxx PIV
        assert_equal(9, self.len_listunspent({}))
        assert_equal(9, self.len_listunspent({"maximumCount": 10}))
        assert_equal(2, self.len_listunspent({"maximumCount": 2}))
        assert_equal(1, self.len_listunspent({"maximumCount": 1}))
        assert_equal(9, self.len_listunspent({"maximumCount": 0}))
        assert_equal(9, self.len_listunspent({"minimumAmount": 0.99999999}))
        assert_equal(9, self.len_listunspent({"minimumAmount": 1.00}))
        assert_equal(8, self.len_listunspent({"minimumAmount": 1.00000001}))
        assert_equal(8, self.len_listunspent({"minimumAmount": 228.9999}))
        assert_equal(7, self.len_listunspent({"minimumAmount": 229.00}))
        assert_equal(7, self.len_listunspent({"minimumAmount": 250.00}))
        assert_equal(0, self.len_listunspent({"minimumAmount": 250.00000001}))
        assert_equal(0, self.len_listunspent({"maximumAmount": 0.99999999}))
        assert_equal(1, self.len_listunspent({"maximumAmount": 1.00}))
        assert_equal(1, self.len_listunspent({"maximumAmount": 228.9999}))
        assert_equal(2, self.len_listunspent({"maximumAmount": 229.00}))
        assert_equal(2, self.len_listunspent({"maximumAmount": 249.99999999}))
        assert_equal(9, self.len_listunspent({"maximumAmount": 250.00}))
        assert_equal(
            9,
            self.len_listunspent({
                "minimumAmount": 1.00000000,
                "maximumAmount": 250.00
            }))
        assert_equal(
            2,
            self.len_listunspent({
                "minimumAmount": 1.00000000,
                "maximumAmount": 249.99999999
            }))
        assert_equal(
            8,
            self.len_listunspent({
                "minimumAmount": 1.00000001,
                "maximumAmount": 250.00
            }))
        assert_equal(
            7,
            self.len_listunspent({
                "minimumAmount": 229.000000,
                "maximumAmount": 250.00
            }))
        assert_equal(
            7,
            self.len_listunspent({
                "minimumAmount": 250.000000,
                "maximumAmount": 250.00
            }))
        assert_equal(
            8,
            self.len_listunspent({
                "minimumAmount": 228.999900,
                "maximumAmount": 250.00
            }))
        assert_equal(
            0,
            self.len_listunspent({
                "minimumAmount": 228.999900,
                "maximumAmount": 228.00
            }))
        assert_equal(
            1,
            self.len_listunspent({
                "minimumAmount": 250.00,
                "minimumSumAmount": 249.99999999
            }))
        assert_equal(
            2,
            self.len_listunspent({
                "minimumAmount": 250.00,
                "minimumSumAmount": 250.00000001
            }))
        assert_equal(
            5,
            self.len_listunspent({
                "minimumAmount": 250.00,
                "minimumSumAmount": 1250.0000000
            }))
        assert_equal(9, self.len_listunspent({"minimumSumAmount": 2500.00}))
Beispiel #10
0
    def test_output_format(self):
        self.node_1_address = self.nodes[1].getnewaddress()
        simple_txid = self.nodes[0].sendtoaddress(self.node_1_address, 0.1)

        internal_transfer_txid = self.nodes[0].sendtoaddress(
            self.nodes[0].getnewaddress(), 0.3)

        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getnewaddress(): 0.33,
            self.node_1_address: 0.44
        }
        several_outs_txid = self.nodes[0].sendmany("", send_to)

        watchonly_address = self.nodes[0].getnewaddress()
        watchonly_pubkey = self.nodes[0].validateaddress(
            watchonly_address)["pubkey"]
        self.nodes[2].importpubkey(watchonly_pubkey, "", True)
        watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address,
                                                     Decimal("0.5"))

        self.sync_all()

        # simple send
        node_0_transactions = self.nodes[0].filtertransactions()
        assert_array_result(node_0_transactions, {"txid": simple_txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 0
        })
        result_tx = next(t for t in node_0_transactions
                         if t["txid"] == simple_txid)
        assert_equal(len(result_tx["outputs"]), 1)
        assert_equal(result_tx["outputs"][0]["address"], self.node_1_address)
        assert_equal(result_tx["outputs"][0]["amount"], Decimal("-0.1"))

        node_1_transactions = self.nodes[1].filtertransactions()
        assert_array_result(node_1_transactions, {"txid": simple_txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 0
        })
        result_tx = next(t for t in node_1_transactions
                         if t["txid"] == simple_txid)
        assert_equal(len(result_tx["outputs"]), 1)
        assert_equal(result_tx["outputs"][0]["address"], self.node_1_address)
        assert_equal(result_tx["outputs"][0]["amount"], Decimal("0.1"))

        # several outputs
        result_tx = next(t for t in self.nodes[0].filtertransactions()
                         if t["txid"] == several_outs_txid)
        assert_equal(len(result_tx["outputs"]), 4)

        # internal transfer
        result_tx = next(t for t in self.nodes[0].filtertransactions()
                         if t["txid"] == internal_transfer_txid)
        assert_equal(result_tx["category"], "internal_transfer")
        assert_equal(result_tx["amount"], Decimal("0"))
        assert_equal(result_tx["outputs"][0]["amount"], Decimal("0.3"))

        # watchonly
        node_2_transactions = self.nodes[2].filtertransactions(
            {"include_watchonly": True})
        assert_array_result(node_2_transactions, {"txid": watchonly_txid}, {
            "category": "receive",
            "amount": Decimal("0.5")
        })
        result_tx = next(t for t in node_2_transactions
                         if t["txid"] == watchonly_txid)
        assert_equal(result_tx["outputs"][0]["involvesWatchonly"], 1)

        result_tx = next((t for t in self.nodes[2].filtertransactions(
            {"include_watchonly": False}) if t["txid"] == watchonly_txid),
                         None)
        assert result_tx is None

        # coinbase
        sync_mempools(self.nodes)
        self.nodes[0].generatetoaddress(
            1, self.nodes[0].getnewaddress())  # Clear node1's mempool
        sync_blocks(self.nodes)

        address = self.nodes[1].getnewaddress()
        self.nodes[1].generatetoaddress(1, address)
        tx = self.nodes[1].filtertransactions({"search": address})[0]
        assert_equal(tx['amount'], PROPOSER_REWARD)
Beispiel #11
0
    def run_test(self):
        assert_raises_rpc_error(-3, 'Not an array', self.nodes[0].sendtypeto, 'unite', 'unite', 'out')

        outputs = [{'address': 'foo', 'amount': 1}]
        assert_raises_rpc_error(-5, 'Invalid Unit-e address', self.nodes[0].sendtypeto, 'unite', 'unite', outputs)

        outputs = [{'address': '2NBYu3St3rtzJb8AzvraXnXCUxEuCs23eZo', 'amount': self.nodes[0].getbalance() + 1}]
        assert_raises_rpc_error(-6, 'Insufficient funds', self.nodes[0].sendtypeto, 'unite', 'unite', outputs)

        # Multiple outputs
        node_1_address = self.nodes[1].getnewaddress()
        outputs = [
            {'address': node_1_address, 'amount': 0.5},
            {'address': '2NBYu3St3rtzJb8AzvraXnXCUxEuCs23eZo', 'amount': 0.25}]
        tx1_id = self.nodes[0].sendtypeto('unite', 'unite', outputs, 'comment', 'comment-to')
        tx = self.nodes[0].getrawtransaction(tx1_id, True)
        assert_equal(len(tx['vout']), 3)
        vout1 = next(o for o in tx['vout'] if node_1_address in o['scriptPubKey']['addresses'])
        assert_equal(vout1['value'], Decimal(0.5))

        # Subtract fee from amount
        outputs = [{'address': node_1_address, 'amount': 0.5, 'subfee': True}]
        tx2_id = self.nodes[0].sendtypeto('unite', 'unite', outputs, 'comment', 'comment-to')
        estimate_fee = True
        fees = self.nodes[0].sendtypeto('unite', 'unite', outputs, 'comment', 'comment-to', estimate_fee)
        tx = self.nodes[0].getrawtransaction(tx2_id, True)
        vout2 = next(o for o in tx['vout'] if node_1_address in o['scriptPubKey']['addresses'])
        assert_equal(vout2['value'], Decimal(0.5) - fees['fee'])

        self.sync_all()
        self.nodes[1].generate(6)

        # coincontrol: inputs
        outputs = [{'address': '2NBYu3St3rtzJb8AzvraXnXCUxEuCs23eZo', 'amount': 0.6}]
        coin_control = {'inputs': [{'tx': tx1_id, 'n': vout1['n']}, {'tx': tx2_id, 'n': vout2['n']}]}
        estimate_fee = False
        tx3_id = self.nodes[1].sendtypeto(
            'unite', 'unite', outputs, 'comment', 'comment-to', estimate_fee, coin_control)
        tx = self.nodes[1].getrawtransaction(tx3_id, True)
        assert_equal(len(tx['vin']), 2)
        assert_array_result(tx['vin'], {'txid': tx1_id}, {'vout': vout1['n']})
        assert_array_result(tx['vin'], {'txid': tx2_id}, {'vout': vout2['n']})

        # coincontrol: changeaddress
        change_address = self.nodes[1].getrawchangeaddress()
        coin_control = {'changeaddress': change_address}
        estimate_fee = False
        tx4_id = self.nodes[1].sendtypeto(
            'unite', 'unite', outputs, 'comment', 'comment-to', estimate_fee, coin_control)
        tx = self.nodes[1].getrawtransaction(tx4_id, True)
        assert_equal(len(tx['vout']), 2)
        next(o for o in tx['vout'] if change_address in o['scriptPubKey']['addresses'])

        # Estimate fee
        estimate_fee = True
        outputs = [{'address': '2NBYu3St3rtzJb8AzvraXnXCUxEuCs23eZo', 'amount': 0.1}]
        fee_per_byte = Decimal('0.001') / 1000
        self.nodes[0].settxfee(fee_per_byte * 1000)
        fees = self.nodes[0].sendtypeto('unite', 'unite', outputs, 'comment', 'comment-to', estimate_fee)
        assert_greater_than(Decimal('1e-7'), abs(fee_per_byte - fees['fee'] / fees['bytes']))

        fee_per_byte *= 2
        coin_control = {'fee_rate': fee_per_byte * 1000}
        fees = self.nodes[0].sendtypeto('unite', 'unite', outputs, 'comment', 'comment-to', estimate_fee, coin_control)
        assert_greater_than(Decimal('1e-7'), abs(fee_per_byte - fees['fee'] / fees['bytes']))
    def run_test(self):
        # Leave IBD
        self.nodes[0].generate(1)
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 10)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-10"), "confirmations": 0})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal('10'), "confirmations": 0})
        # mine a block, confirmations should change:
        blockhash = self.nodes[0].generate(1)[0]
        blockheight = self.nodes[0].getblockheader(blockhash)['height']
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-10"), "confirmations": 1, "blockhash": blockhash, "blockheight": blockheight})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal('10'), "confirmations": 1, "blockhash": blockhash, "blockheight": blockheight})

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 20)
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "send"},
                            {"amount": Decimal("-20")})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "receive"},
                            {"amount": Decimal('20')})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {self.nodes[0].getnewaddress(): 11,
                   self.nodes[1].getnewaddress(): 22,
                   self.nodes[0].getnewaddress(): 33,
                   self.nodes[1].getnewaddress(): 44}
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-11")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal('11')},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-22")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal('22')},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-33")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal('33')},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-44")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal('44')},
                            {"txid": txid})

        pubkey = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        multisig = self.nodes[1].createmultisig(1, [pubkey])
        self.nodes[0].importaddress(
            multisig["redeemScript"], "watchonly", False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 10)
        self.nodes[1].generate(1)
        self.sync_all()
        assert_equal(len(self.nodes[0].listtransactions(
            label="watchonly", include_watchonly=True)), 1)
        assert_equal(len(self.nodes[0].listtransactions(
            dummy="watchonly", include_watchonly=True)), 1)
        assert len(
            self.nodes[0].listtransactions(
                label="watchonly",
                count=100,
                include_watchonly=False)) == 0
        assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
                            {"category": "receive", "amount": Decimal('10')},
                            {"txid": txid, "label": "watchonly"})
    def run_test(self):
        """
        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.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr}, {
                                "address": addr,
                                "account": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        #With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr}, {
                                "address": addr,
                                "account": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        #With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11),
                            {"address": addr}, {}, True)

        #Empty Tx
        addr = self.nodes[1].getnewaddress()
        assert_array_result(self.nodes[1].listreceivedbyaddress(0, True),
                            {"address": addr}, {
                                "address": addr,
                                "account": "",
                                "amount": 0,
                                "confirmations": 0,
                                "txids": []
                            })
        '''
            getreceivedbyaddress Test
        '''
        # Send from node 0 to 1
        addr = self.nodes[1].getnewaddress()
        self.nodes[0].sendtoaddress(addr, 0.1)
        self.sync_all()

        # Check balance is 0 because of 0 confirmations
        balance = self.nodes[1].getreceivedbyaddress(addr)
        if balance != Decimal("0.0"):
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaddress, %0.2f" %
                balance)

        # Check balance is 0.1
        balance = self.nodes[1].getreceivedbyaddress(addr, 0)
        if balance != Decimal("0.1"):
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaddress, %0.2f" %
                balance)

        # Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
        self.nodes[1].generate(10)
        self.sync_all()
        balance = self.nodes[1].getreceivedbyaddress(addr)
        if balance != Decimal("0.1"):
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaddress, %0.2f" %
                balance)
        '''
            listreceivedbyaccount + getreceivedbyaccount Test
        '''
        # set pre-state
        addrArr = self.nodes[1].getnewaddress()
        account = self.nodes[1].getaccount(addrArr)
        received_by_account_json = get_sub_array_from_array(
            self.nodes[1].listreceivedbyaccount(), {"account": account})
        if len(received_by_account_json) == 0:
            raise AssertionError("No accounts found in node")
        balance_by_account = self.nodes[1].getreceivedbyaccount(account)

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

        # listreceivedbyaccount should return received_by_account_json because of 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbyaccount(),
                            {"account": account}, received_by_account_json)

        # getreceivedbyaddress should return same balance because of 0 confirmations
        balance = self.nodes[1].getreceivedbyaccount(account)
        if balance != balance_by_account:
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaccount, %0.2f" %
                balance)

        self.nodes[1].generate(10)
        self.sync_all()
        # listreceivedbyaccount should return updated account balance
        assert_array_result(
            self.nodes[1].listreceivedbyaccount(), {"account": account}, {
                "account": received_by_account_json["account"],
                "amount": (received_by_account_json["amount"] + Decimal("0.1"))
            })

        # getreceivedbyaddress should return updates balance
        balance = self.nodes[1].getreceivedbyaccount(account)
        if balance != balance_by_account + Decimal("0.1"):
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaccount, %0.2f" %
                balance)

        # Create a new account named "mynewaccount" that has a 0 balance
        self.nodes[1].getaccountaddress("mynewaccount")
        received_by_account_json = get_sub_array_from_array(
            self.nodes[1].listreceivedbyaccount(0, True),
            {"account": "mynewaccount"})
        if len(received_by_account_json) == 0:
            raise AssertionError("No accounts found in node")

        # Test include empty of listreceivedbyaccount
        if received_by_account_json["amount"] != Decimal("0.0"):
            raise AssertionError(
                "Wrong balance returned by listreceivedbyaccount, %0.2f" %
                (received_by_account_json["amount"]))

        # Test getreceivedbyaccount for 0 amount accounts
        balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
        if balance != Decimal("0.0"):
            raise AssertionError(
                "Wrong balance returned by getreceivedbyaccount, %0.2f" %
                balance)
Beispiel #14
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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 250)
        assert_equal(walletinfo['balance'], 0)

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

        assert_equal(self.nodes[0].getbalance(), 250)
        assert_equal(self.nodes[1].getbalance(), 250)
        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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        # Send 21 PIV from 0 to 2 using sendtoaddress call.
        # Second transaction will be child of first, and will require a fee
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 21)
        #self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        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"]}
        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)

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

        # node0 should end up with 100 PIV in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 500 - 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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            inputs = []
            outputs = {}
            inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
            outputs[self.nodes[2].getnewaddress("from1")] = float(
                utxo["amount"])
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))

        # 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)

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

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 500)
        assert_equal(self.nodes[2].getbalance("from1"), 500 - 21)

        # Send 10 PIV normal
        address = self.nodes[0].getnewaddress("test")
        fee_per_byte = Decimal('0.001') / 1000
        self.nodes[2].settxfee(float(fee_per_byte * 1000))
        txid = self.nodes[2].sendtoaddress(address, 10, "", "")
        fee = self.nodes[2].gettransaction(txid)["fee"]
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal = self.nodes[2].getbalance()
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 PIV with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "")
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance() - fee, node_2_bal)
        node_0_bal = self.nodes[0].getbalance()
        assert_equal(node_0_bal, Decimal('20'))

        # Sendmany 10 PIV
        txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "")
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_0_bal += Decimal('10')
        node_2_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 PIV with subtract fee from amount
        txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "")
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal + (fee * 3))
        #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.start_node(3)
        connect_nodes(self.nodes[0], 3)
        sync_blocks(self.nodes)

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

        #check if we can list zero value tx as available coins
        #1. create rawtx
        #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()
        inputs = [{"txid": usp[0]['txid'], "vout": usp[0]['vout']}]
        outputs = {
            self.nodes[1].getnewaddress(): 49.998,
            self.nodes[0].getnewaddress(): 11.11
        }

        rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace(
            "c0833842", "00000000")  #replace 11.11 with 0.0 (int32)
        decRawTx = self.nodes[1].decoderawtransaction(rawTx)
        signedRawTx = self.nodes[1].signrawtransaction(rawTx)
        decRawTx = self.nodes[1].decoderawtransaction(signedRawTx['hex'])
        zeroValueTxid = decRawTx['txid']
        assert_raises_rpc_error(-25, "", self.nodes[1].sendrawtransaction,
                                signedRawTx['hex'])

        # 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")

        # 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.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].validateaddress(address_to_import)["iswatchonly"])

        # 4. Check that the unspents after import are not spendable
        listunspent = self.nodes[1].listunspent(1, 9999999, [], 3)
        assert_array_result(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})

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

        maintenance = [
            '-rescan',
            '-reindex',
            '-zapwallettxes=1',
            '-zapwallettxes=2',
            #'-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)
Beispiel #15
0
    def run_test(self):
        # Leave IBD
        self.nodes[0].generate(1)
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "account": "",
            "amount": Decimal("-0.1"),
            "confirmations": 0
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "account": "",
            "amount": Decimal("0.1"),
            "confirmations": 0
        })
        # mine a block, confirmations should change:
        self.nodes[0].generate(1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "account": "",
            "amount": Decimal("-0.1"),
            "confirmations": 1
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "account": "",
            "amount": Decimal("0.1"),
            "confirmations": 1
        })

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "send"
        }, {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "receive"
        }, {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getaccountaddress("from1"): 0.33,
            self.nodes[1].getaccountaddress("toself"): 0.44
        }
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.33")
        }, {
            "txid": txid,
            "account": "from1"
        })
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.44")
        }, {
            "txid": txid,
            "account": ""
        })
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.44")
        }, {
            "txid": txid,
            "account": "toself"
        })

        multisig = self.nodes[1].createmultisig(
            1, [self.nodes[1].getnewaddress()])
        self.nodes[0].importaddress(multisig["redeemScript"], "watchonly",
                                    False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
        self.nodes[1].generate(1)
        self.sync_all()
        assert (len(self.nodes[0].listtransactions("watchonly", 100, 0,
                                                   False)) == 0)
        assert_array_result(
            self.nodes[0].listtransactions("watchonly", 100, 0, True), {
                "category": "receive",
                "amount": Decimal("0.1")
            }, {
                "txid": txid,
                "account": "watchonly"
            })
    def run_test(self):
        # Generate block to get out of IBD
        self.nodes[0].generate(1)

        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.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr},
                            {"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr},
                            {"address": addr, "account": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True)

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

        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].getreceivedbyaddress(addr, 0)
        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.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("listreceivedbyaccount + getreceivedbyaccount Test")

        # set pre-state
        addrArr = self.nodes[1].getnewaddress()
        account = self.nodes[1].getaccount(addrArr)
        received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount() if r["account"] == account][0]
        balance_by_account = self.nodes[1].getreceivedbyaccount(account)

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

        # listreceivedbyaccount should return received_by_account_json because of 0 confirmations
        assert_array_result(self.nodes[1].listreceivedbyaccount(),
                            {"account": account},
                            received_by_account_json)

        # getreceivedbyaddress should return same balance because of 0 confirmations
        balance = self.nodes[1].getreceivedbyaccount(account)
        assert_equal(balance, balance_by_account)

        self.nodes[1].generate(10)
        self.sync_all()
        # listreceivedbyaccount should return updated account balance
        assert_array_result(self.nodes[1].listreceivedbyaccount(),
                            {"account": account},
                            {"account": received_by_account_json["account"], "amount": (received_by_account_json["amount"] + Decimal("0.1"))})

        # getreceivedbyaddress should return updates balance
        balance = self.nodes[1].getreceivedbyaccount(account)
        assert_equal(balance, balance_by_account + Decimal("0.1"))

        # Create a new account named "mynewaccount" that has a 0 balance
        self.nodes[1].getaccountaddress("mynewaccount")
        received_by_account_json = [r for r in self.nodes[1].listreceivedbyaccount(0, True) if r["account"] == "mynewaccount"][0]

        # Test includeempty of listreceivedbyaccount
        assert_equal(received_by_account_json["amount"], Decimal("0.0"))

        # Test getreceivedbyaccount for 0 amount accounts
        balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
        assert_equal(balance, Decimal("0.0"))
Beispiel #17
0
    def run_with_paginatebypointer_test(self):
        def get_with_paginatebypointer(node, count=20, label="*", watchonly=False):
            i = 1
            records = []
            pointer = None
            while i < count:
                options = {
                    "paginatebypointer": True,
                    "nextpagepointer": pointer,
                }
                #if pointer is None:
                #    del options["nextpagepointer"]
                result = node.listtransactions(label, i, 0, watchonly, options)
                pointer = result.get("nextpagepointer", None)
                records += result["records"]
                if len(records) >= count or pointer is None:
                    break
                i += 1
            return records
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(get_with_paginatebypointer(self.nodes[0]),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {self.nodes[0].getnewaddress(): 0.111,
                   self.nodes[1].getnewaddress(): 0.222,
                   self.nodes[0].getnewaddress(): 0.333,
                   self.nodes[1].getnewaddress(): 0.444}
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "send", "amount": Decimal("-0.111")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[0]),
                            {"category": "receive", "amount": Decimal("0.111")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "send", "amount": Decimal("-0.222")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "receive", "amount": Decimal("0.222")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "send", "amount": Decimal("-0.333")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[0]),
                            {"category": "receive", "amount": Decimal("0.333")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "send", "amount": Decimal("-0.444")},
                            {"txid": txid})
        assert_array_result(get_with_paginatebypointer(self.nodes[1]),
                            {"category": "receive", "amount": Decimal("0.444")},
                            {"txid": txid})
Beispiel #18
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.generate(self.nodes[0], 1, sync_fun=self.no_op)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 50)
        assert_equal(walletinfo['balance'], 0)

        self.sync_all(self.nodes[0:3])
        self.generate(self.nodes[1], COINBASE_MATURITY + 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("Test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[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(txout['value'], 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 50)

        # Send 21 BTC from 0 to 2 using sendtoaddress call.
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)

        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(txout['value'], 50)
        txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index)  # by default include_mempool=True
        assert txout is None
        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_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 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(set([txout1['value'], txout2['value']]), set([10, balance]))
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.generate(self.nodes[0], 1, sync_fun=lambda: 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"]}
        # Trying to unlock an output which isn't locked should error
        assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", self.nodes[2].lockunspent, True, [unspent_0])

        # Locking an already-locked output should error
        self.nodes[2].lockunspent(False, [unspent_0])
        assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])

        # Restarting the node should clear the lock
        self.restart_node(2)
        self.nodes[2].lockunspent(False, [unspent_0])

        # Unloading and reloating the wallet should clear the lock
        assert_equal(self.nodes[0].listwallets(), [self.default_wallet_name])
        self.nodes[2].unloadwallet(self.default_wallet_name)
        self.nodes[2].loadwallet(self.default_wallet_name)
        assert_equal(len(self.nodes[2].listlockunspent()), 0)

        # Locking non-persistently, then re-locking persistently, is allowed
        self.nodes[2].lockunspent(False, [unspent_0])
        self.nodes[2].lockunspent(False, [unspent_0], True)

        # Restarting the node with the lock written to the wallet should keep the lock
        self.restart_node(2)
        assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])

        # Unloading and reloading the wallet with a persistent lock should keep the lock
        self.nodes[2].unloadwallet(self.default_wallet_name)
        self.nodes[2].loadwallet(self.default_wallet_name)
        assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])

        # Locked outputs should not be used, even if they are the only available funds
        assert_raises_rpc_error(-6, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
        assert_equal([unspent_0], self.nodes[2].listlockunspent())

        # Unlocking should remove the persistent lock
        self.nodes[2].lockunspent(True, [unspent_0])
        self.restart_node(2)
        assert_equal(len(self.nodes[2].listlockunspent()), 0)

        # Reconnect node 2 after restarts
        self.connect_nodes(1, 2)
        self.connect_nodes(0, 2)

        assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "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}])

        # The lock on a manually selected output is ignored
        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 })
        self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})

        # fundrawtransaction can lock an input
        self.nodes[1].lockunspent(True, [unspent_0])
        assert_equal(len(self.nodes[1].listlockunspent()), 0)
        tx = self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})['hex']
        assert_equal(len(self.nodes[1].listlockunspent()), 1)

        # Send transaction
        tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

        # Have node1 generate 100 blocks (so node0 can recover the fee)
        self.generate(self.nodes[1], COINBASE_MATURITY, sync_fun=lambda: self.sync_all(self.nodes[0:3]))

        # node0 should end up with 100 btc in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 100 - 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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            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))

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

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

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

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

        # Send 10 BTC 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)
        self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.generate(self.nodes[2], 1, sync_fun=lambda: 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].gettransaction(txid)['hex']))

        self.log.info("Test sendmany")

        # Sendmany 10 BTC
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
        self.generate(self.nodes[2], 1, sync_fun=lambda: 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].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
        self.generate(self.nodes[2], 1, sync_fun=lambda: 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].gettransaction(txid)['hex']))

        self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)")
        fee_rate_sat_vb = 2
        fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
        explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000

        # Test passing fee_rate as a string
        txid = self.nodes[2].sendmany(amounts={address: 10}, fee_rate=str(fee_rate_sat_vb))
        self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
        balance = self.nodes[2].getbalance()
        node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(balance, node_2_bal)
        node_0_bal += Decimal('10')
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Test passing fee_rate as an integer
        amount = Decimal("0.0001")
        txid = self.nodes[2].sendmany(amounts={address: amount}, fee_rate=fee_rate_sat_vb)
        self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
        balance = self.nodes[2].getbalance()
        node_2_bal = self.check_fee_amount(balance, node_2_bal - amount, explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(balance, node_2_bal)
        node_0_bal += amount
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        for key in ["totalFee", "feeRate"]:
            assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)

        # Test setting explicit fee rate just below the minimum.
        self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
        assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
            self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.999)

        self.log.info("Test sendmany raises if an invalid fee_rate is passed")
        # Test fee_rate with zero values.
        msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"
        for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]:
            assert_raises_rpc_error(-6, msg, self.nodes[2].sendmany, amounts={address: 1}, fee_rate=zero_value)
        msg = "Invalid amount"
        # Test fee_rate values that don't pass fixed-point parsing checks.
        for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
            assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 1.0}, fee_rate=invalid_value)
        # Test fee_rate values that cannot be represented in sat/vB.
        for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
            assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=invalid_value)
        # Test fee_rate out of range (negative number).
        assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
        # Test type error.
        for invalid_value in [True, {"foo": "bar"}]:
            assert_raises_rpc_error(-3, NOT_A_NUMBER_OR_STRING, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=invalid_value)

        self.log.info("Test sendmany raises if an invalid conf_target or estimate_mode is passed")
        for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
            assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008",  # max value of 1008 per src/policy/fees.h
                self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
        for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
            assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
                self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)

        self.start_node(3, self.nodes[3].extra_args)
        self.connect_nodes(0, 3)
        self.sync_all()

        # 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)
        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'])

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

        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

        self.log.info("Test -walletbroadcast")
        self.stop_nodes()
        self.start_node(0, ["-walletbroadcast=0"])
        self.start_node(1, ["-walletbroadcast=0"])
        self.start_node(2, ["-walletbroadcast=0"])
        self.connect_nodes(0, 1)
        self.connect_nodes(1, 2)
        self.connect_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.generate(self.nodes[1], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))  # mine a block, tx should not be in there
        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.generate(self.nodes[1], 1, sync_fun=lambda: 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)
        self.connect_nodes(0, 1)
        self.connect_nodes(1, 2)
        self.connect_nodes(0, 2)
        self.sync_blocks(self.nodes[0:3])

        self.generate(self.nodes[0], 1, sync_fun=lambda: self.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'))

        # General checks for errors from incorrect inputs
        # This will raise an exception because the amount is negative
        assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1")

        # 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.generate, self.nodes[0], "2")

        if not self.options.descriptors:

            # This will raise an exception for the invalid private key format
            assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")

            # This will raise an exception for importing an address with the PS2H flag
            temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
            assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)

            # This will raise an exception for attempting to dump the private key of an address you do not own
            assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)

            # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].dumpprivkey, "invalid")

            # This will raise an exception for attempting to set a label for an invalid Bitcoin address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].setlabel, "invalid address", "label")

            # This will raise an exception for importing an invalid address
            assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid")

            # This will raise an exception for attempting to import a pubkey that isn't in hex
            assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")

            # This will raise an exception for importing an invalid pubkey
            assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")

            # Bech32m addresses cannot be imported into a legacy wallet
            assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6")

            # 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.sync_mempools(self.nodes[0:3])
            vout = find_vout_for_address(self.nodes[2], txid, address_to_import)
            self.nodes[2].lockunspent(False, [{"txid": txid, "vout": vout}])
            self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))

            self.log.info("Test sendtoaddress with fee_rate param (explicit fee rate in sat/vB)")
            prebalance = self.nodes[2].getbalance()
            assert prebalance > 2
            address = self.nodes[1].getnewaddress()
            amount = 3
            fee_rate_sat_vb = 2
            fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
            # Test passing fee_rate as an integer
            txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb)
            tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
            self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
            postbalance = self.nodes[2].getbalance()
            fee = prebalance - postbalance - Decimal(amount)
            assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))

            prebalance = self.nodes[2].getbalance()
            amount = Decimal("0.001")
            fee_rate_sat_vb = 1.23
            fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
            # Test passing fee_rate as a string
            txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=str(fee_rate_sat_vb))
            tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
            self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
            postbalance = self.nodes[2].getbalance()
            fee = prebalance - postbalance - amount
            assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))

            for key in ["totalFee", "feeRate"]:
                assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)

            # Test setting explicit fee rate just below the minimum.
            self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
            assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
                self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.999)

            self.log.info("Test sendtoaddress raises if an invalid fee_rate is passed")
            # Test fee_rate with zero values.
            msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"
            for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]:
                assert_raises_rpc_error(-6, msg, self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=zero_value)
            msg = "Invalid amount"
            # Test fee_rate values that don't pass fixed-point parsing checks.
            for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
                assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=invalid_value)
            # Test fee_rate values that cannot be represented in sat/vB.
            for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
                assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=invalid_value)
            # Test fee_rate out of range (negative number).
            assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)
            # Test type error.
            for invalid_value in [True, {"foo": "bar"}]:
                assert_raises_rpc_error(-3, NOT_A_NUMBER_OR_STRING, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=invalid_value)

            self.log.info("Test sendtoaddress raises if an invalid conf_target or estimate_mode is passed")
            for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
                assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008",  # max value of 1008 per src/policy/fees.h
                    self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
            for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
                assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
                    self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)

            # 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.generatetoaddress(self.nodes[0], 1, coinbase_addr, sync_fun=lambda: self.sync_all(self.nodes[0:3]))[0]
        coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]

        # 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.generate(self.nodes[0], 2, sync_fun=lambda: 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)
                test_address(self.nodes[0], addr, labels=[label])
                assert label in self.nodes[0].listlabels()
        self.nodes[0].rpc.ensure_ascii = True  # restore to default

        # -reindex tests
        chainlimit = 6
        self.log.info("Test -reindex")
        self.stop_nodes()
        # set lower ancestor limit for later
        self.start_node(0, ['-reindex', "-limitancestorcount=" + str(chainlimit)])
        self.start_node(1, ['-reindex', "-limitancestorcount=" + str(chainlimit)])
        self.start_node(2, ['-reindex', "-limitancestorcount=" + str(chainlimit)])
        # reindex will leave rpc warm up "early"; Wait for it to finish
        self.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)
        self.generate(self.nodes[0], 1, sync_fun=self.no_op)
        node0_balance = self.nodes[0].getbalance()
        # 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)
        singletxid = self.nodes[0].sendrawtransaction(hexstring=signedtx["hex"], maxfeerate=0)
        self.generate(self.nodes[0], 1, sync_fun=self.no_op)

        # 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 _ in range(chainlimit * 2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
        assert_equal(len(txid_list), chainlimit * 2)

        # 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 AttemptSelection
        self.stop_node(0)
        extra_args = ["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]
        self.start_node(0, extra_args=extra_args)

        # wait until the wallet has submitted all transactions to the mempool
        self.wait_until(lambda: len(self.nodes[0].getrawmempool()) == chainlimit * 2)

        # Prevent potential race condition when calling wallet RPCs right after restart
        self.nodes[0].syncwithvalidationinterfacequeue()

        node0_balance = self.nodes[0].getbalance()
        # With walletrejectlongchains we will not create the tx and store it in our wallet.
        assert_raises_rpc_error(-6, "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 on external address. Note that these addresses are taken from disablewallet.py
        assert_raises_rpc_error(-5, "Invalid prefix for Base58-encoded 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"]
        assert not address_info["ischange"]
        assert_equal(address_info['use_txids'], [])

        # Test getaddressinfo 'txids' field
        txid = self.nodes[0].sendtoaddress("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ", 1)
        address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
        assert_equal(address_info['use_txids'], [txid])

        # Test getaddressinfo 'ischange' field on change address.
        self.generate(self.nodes[0], 1, sync_fun=self.no_op)
        destination = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(destination, 0.123)
        tx = self.nodes[0].gettransaction(txid=txid, verbose=True)['decoded']
        output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
        assert len(output_addresses) > 1
        for address in output_addresses:
            ischange = self.nodes[0].getaddressinfo(address)['ischange']
            assert_equal(ischange, address != destination)
            if ischange:
                change = address
        self.nodes[0].setlabel(change, 'foobar')
        assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)

        # Test gettransaction response with different arguments.
        self.log.info("Testing gettransaction response with different arguments...")
        self.nodes[0].setlabel(change, 'baz')
        baz = self.nodes[0].listtransactions(label="baz", count=1)[0]
        expected_receive_vout = {"label":    "baz",
                                 "address":  baz["address"],
                                 "amount":   baz["amount"],
                                 "category": baz["category"],
                                 "vout":     baz["vout"]}
        expected_fields = frozenset({
            'amount',
            'bip125-replaceable',
            'confirmations',
            'details',
            'fee',
            'hex',
            'in_mempool',
            'lastprocessedblock',
            'time',
            'timereceived',
            'trusted',
            'txid',
            'walletconflicts',
            'wtxid',
        })
        verbose_field = "decoded"
        expected_verbose_fields = expected_fields | {verbose_field}

        self.log.debug("Testing gettransaction response without verbose")
        tx = self.nodes[0].gettransaction(txid=txid)
        assert_equal(set([*tx]), expected_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)

        self.log.debug("Testing gettransaction response with verbose set to False")
        tx = self.nodes[0].gettransaction(txid=txid, verbose=False)
        assert_equal(set([*tx]), expected_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)

        self.log.debug("Testing gettransaction response with verbose set to True")
        tx = self.nodes[0].gettransaction(txid=txid, verbose=True)
        assert_equal(set([*tx]), expected_verbose_fields)
        assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)
        assert_equal(tx[verbose_field], self.nodes[0].decoderawtransaction(tx["hex"]))

        self.log.info("Test send* RPCs with verbose=True")
        address = self.nodes[0].getnewaddress("test")
        txid_feeReason_one = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=True)
        assert_equal(txid_feeReason_one["fee_reason"], "Fallback fee")
        txid_feeReason_two = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=True)
        assert_equal(txid_feeReason_two["fee_reason"], "Fallback fee")
        self.log.info("Test send* RPCs with verbose=False")
        txid_feeReason_three = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=False)
        assert_equal(self.nodes[2].gettransaction(txid_feeReason_three)['txid'], txid_feeReason_three)
        txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
        assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
Beispiel #19
0
    def run_test(self):
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                           {"txid": txid},
                           {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"txid": txid},
                           {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0})
        # mine a block, confirmations should change:
        self.nodes[0].generate(1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                           {"txid": txid},
                           {"category": "send", "amount": Decimal("-0.1"), "confirmations": 1})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"txid": txid},
                           {"category": "receive", "amount": Decimal("0.1"), "confirmations": 1})

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(),
                           {"txid": txid, "category": "send"},
                           {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(),
                           {"txid": txid, "category": "receive"},
                           {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {self.nodes[0].getnewaddress(): 0.11,
                   self.nodes[1].getnewaddress(): 0.22,
                   self.nodes[0].getnewaddress(): 0.33,
                   self.nodes[1].getnewaddress(): 0.44}
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category":"send", "amount": Decimal("-0.11")},
                           {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                           {"category": "receive", "amount": Decimal("0.11")},
                           {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category": "send", "amount": Decimal("-0.22")},
                           {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category": "receive", "amount": Decimal("0.22")},
                           {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category": "send", "amount": Decimal("-0.33")},
                           {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                           {"category": "receive", "amount": Decimal("0.33")},
                           {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category": "send", "amount": Decimal("-0.44")},
                           {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                           {"category": "receive", "amount": Decimal("0.44")},
                           {"txid": txid})

        multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
        self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
        self.nodes[1].generate(1)
        self.sync_all()
        assert not [tx for tx in self.nodes[0].listtransactions("*", 100, 0, False) if "label" in tx and tx["label"] == "watchonly"]
        txs = [tx for tx in self.nodes[0].listtransactions("*", 100, 0, True) if "label" in tx and tx['label'] == 'watchonly']
        assert_array_result(txs, {"category": "receive", "amount": Decimal("0.1")}, {"txid": txid})
    def run_test(self):
        # Leave IBD
        self.generate(self.nodes[0], 1)
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 0
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 0
        })
        # mine a block, confirmations should change:
        self.generate(self.nodes[0], 1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 1
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 1
        })

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "send"
        }, {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "receive"
        }, {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getnewaddress(): 0.33,
            self.nodes[1].getnewaddress(): 0.44
        }
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.44")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.44")
        }, {"txid": txid})

        pubkey_A = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        multisig_A = self.nodes[1].createmultisig(1, [pubkey_A])
        self.nodes[0].importaddress(multisig_A["redeemScript"],
                                    "label_A_watchonly", False, True)

        pubkey_B = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        multisig_B = self.nodes[1].createmultisig(1, [pubkey_B])
        self.nodes[0].importaddress(multisig_B["redeemScript"],
                                    "label_B_watchonly", False, True)

        plain_addr_C = self.nodes[1].getnewaddress()
        pubkey_C = self.nodes[1].getaddressinfo(plain_addr_C)['pubkey']
        self.nodes[0].importpubkey(pubkey_C, "label_C", False)

        num_wildcard_label_results_before_txs = len(
            self.nodes[0].listtransactions(label="*",
                                           count=100,
                                           include_watchonly=True))

        txid_A = self.nodes[1].sendtoaddress(multisig_A["address"], 0.01)
        txid_B = self.nodes[1].sendtoaddress(multisig_B["address"], 0.01)
        txid_C = self.nodes[1].sendtoaddress(plain_addr_C, 0.01)

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

        # check label_A_watchonly results
        assert len(
            self.nodes[0].listtransactions(label="label_A_watchonly",
                                           count=100,
                                           include_watchonly=False)) == 0
        assert len(self.nodes[0].listtransactions(label="label_A_watchonly",
                                                  count=100,
                                                  include_watchonly=True)) == 1

        # check label_B_watchonly results
        assert len(
            self.nodes[0].listtransactions(label="label_B_watchonly",
                                           count=100,
                                           include_watchonly=False)) == 0
        assert len(self.nodes[0].listtransactions(label="label_B_watchonly",
                                                  count=100,
                                                  include_watchonly=True)) == 1

        # check label_C results
        assert len(self.nodes[0].listtransactions(
            label="label_C", count=100, include_watchonly=False)) == 0
        assert len(self.nodes[0].listtransactions(label="label_C",
                                                  count=100,
                                                  include_watchonly=True)) == 1

        # check no results returned for unknown label
        assert len(self.nodes[0].listtransactions(label="no_such_label",
                                                  count=100,
                                                  include_watchonly=True)) == 0

        # wildcard labels : 3 new txs added (A, B & C)
        assert len(self.nodes[0].listtransactions(
            label='*', count=100, include_watchonly=True)
                   ) - num_wildcard_label_results_before_txs == 3

        # check wildcard returns all labeled txs
        assert_array_result(self.nodes[0].listtransactions(
            label="*", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_A_watchonly",
                "amount": Decimal("0.01")
            }, {
                "txid": txid_A,
                "label": "label_A_watchonly"
            },
                            should_not_find=False)
        assert_array_result(self.nodes[0].listtransactions(
            label="*", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_B_watchonly",
                "amount": Decimal("0.01")
            }, {
                "txid": txid_B,
                "label": "label_B_watchonly"
            },
                            should_not_find=False)
        assert_array_result(self.nodes[0].listtransactions(
            label="*", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_C",
                "amount": Decimal("0.01")
            }, {
                "txid": txid_C,
                "label": "label_C"
            },
                            should_not_find=False)

        # check label A returns only label A, not B or C
        assert_array_result(
            self.nodes[0].listtransactions(label="label_A_watchonly",
                                           count=100,
                                           include_watchonly=True), {
                                               "category": "receive",
                                               "label": "label_A_watchonly",
                                               "amount": Decimal("0.01")
                                           }, {
                                               "txid": txid_A,
                                               "label": "label_A_watchonly"
                                           })
        assert_array_result(self.nodes[0].listtransactions(
            label="label_A_watchonly", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_B_watchonly",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)
        assert_array_result(self.nodes[0].listtransactions(
            label="label_A_watchonly", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_C",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)

        # check label B returns only label B, not A or C
        assert_array_result(
            self.nodes[0].listtransactions(label="label_B_watchonly",
                                           count=100,
                                           include_watchonly=True), {
                                               "category": "receive",
                                               "label": "label_B_watchonly",
                                               "amount": Decimal("0.01")
                                           }, {
                                               "txid": txid_B,
                                               "label": "label_B_watchonly"
                                           })
        assert_array_result(self.nodes[0].listtransactions(
            label="label_B_watchonly", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_A_watchonly",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)
        assert_array_result(self.nodes[0].listtransactions(
            label="label_B_watchonly", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_C",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)

        # check label C returns only label C, not A or B
        assert_array_result(
            self.nodes[0].listtransactions(label="label_C",
                                           count=100,
                                           include_watchonly=True), {
                                               "category": "receive",
                                               "label": "label_C",
                                               "amount": Decimal("0.01")
                                           }, {
                                               "txid": txid_C,
                                               "label": "label_C"
                                           })
        assert_array_result(self.nodes[0].listtransactions(
            label="label_C", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_A_watchonly",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)
        assert_array_result(self.nodes[0].listtransactions(
            label="label_C", count=100, include_watchonly=True), {
                "category": "receive",
                "label": "label_B_watchonly",
                "amount": Decimal("0.01")
            }, {},
                            should_not_find=True)
Beispiel #21
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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 50)
        assert_equal(walletinfo['balance'], 0)

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

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

        # Check getbalance with different arguments
        assert_equal(self.nodes[0].getbalance("*"), 50)
        assert_equal(self.nodes[0].getbalance("*", 1), 50)
        assert_equal(self.nodes[0].getbalance("*", 1, True), 50)
        assert_equal(self.nodes[0].getbalance(minconf=1), 50)

        # first argument of getbalance must be excluded or set to "*"
        assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[0].getbalance, "")

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

        self.log.info("test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[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(txout['value'], 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 50)

        # Send 21 TCS 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()
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = 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(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_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 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(set([txout1['value'], txout2['value']]), set([10, balance]))
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        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)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

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

        # node0 should end up with 100 btc in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 100 - 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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            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))

        # 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)

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

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

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

        # Send 10 TCS 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)
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 TCS with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.nodes[2].generate(1)
        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 TCS
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
        self.nodes[2].generate(1)
        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 TCS with subtract fee from amount
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
        self.nodes[2].generate(1)
        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.start_node(3)
        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"], 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)
        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'])

        self.sync_all()
        self.nodes[1].generate(1)  # 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)  # 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.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)
        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")

        # 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.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)[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.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/testcoinsuper/testcoinsuper/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)
        self.nodes[0].generate(1)
        node0_balance = self.nodes[0].getbalance()
        # 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)
        singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)

        # 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 * 2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
        assert_equal(len(txid_list), chainlimit * 2)

        # 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 * 2):
            time.sleep(0.5)
            timeout -= 0.5
        assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)

        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"]
Beispiel #22
0
    def run_test(self):
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1000)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-1000"), "confirmations": 0})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal("1000"), "confirmations": 0})
        # mine a block, confirmations should change:
        self.nodes[0].generate(1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid},
                            {"category": "send", "amount": Decimal("-1000"), "confirmations": 1})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid},
                            {"category": "receive", "amount": Decimal("1000"), "confirmations": 1})

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2000)
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "send"},
                            {"amount": Decimal("-2000")})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid, "category": "receive"},
                            {"amount": Decimal("2000")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {self.nodes[0].getnewaddress(): 1100,
                   self.nodes[1].getnewaddress(): 2200,
                   self.nodes[0].getnewaddress(): 3300,
                   self.nodes[1].getnewaddress(): 4400}
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-1100")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal("1100")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-2200")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal("2200")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-3300")},
                            {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(),
                            {"category": "receive", "amount": Decimal("3300")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "send", "amount": Decimal("-4400")},
                            {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(),
                            {"category": "receive", "amount": Decimal("4400")},
                            {"txid": txid})

        pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
        multisig = self.nodes[1].createmultisig(1, [pubkey])
        self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 1000)
        self.nodes[1].generate(1)
        self.sync_all()
        assert not [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=False) if "label" in tx and tx["label"] == "watchonly"]
        txs = [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=True) if "label" in tx and tx['label'] == 'watchonly']
        assert_array_result(txs, {"category": "receive", "amount": Decimal("1000")}, {"txid": txid})

        self.run_rbf_opt_in_test()
Beispiel #23
0
    def run_test(self):
        self.nodes[0].generate(1)  # Get out of IBD
        self.sync_all()
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 0
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 0
        })
        # mine a block, confirmations should change:
        self.nodes[0].generate(1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 1
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 1
        })

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "send"
        }, {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "receive"
        }, {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getnewaddress(): 0.33,
            self.nodes[1].getnewaddress(): 0.44
        }
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.44")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.44")
        }, {"txid": txid})

        pubkey = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        multisig = self.nodes[1].createmultisig(1, [pubkey])
        self.nodes[0].importaddress(multisig["redeemScript"], "watchonly",
                                    False, True)
        txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
        self.nodes[1].generate(1)
        self.sync_all()
        assert len(self.nodes[0].listtransactions(
            label="watchonly", count=100, include_watchonly=False)) == 0
        assert_array_result(
            self.nodes[0].listtransactions(label="watchonly",
                                           count=100,
                                           include_watchonly=True), {
                                               "category": "receive",
                                               "amount": Decimal("0.1")
                                           }, {
                                               "txid": txid,
                                               "label": "watchonly"
                                           })

        self.run_rbf_opt_in_test()
    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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 1)
        assert_equal(walletinfo['balance']['TPC'], 50)

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

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

        #  PART 1: using cp2pkh address
        #
        utxo = self.nodes[0].listunspent()[0]
        new_address = self.nodes[0].getnewaddress()
        pubkeyhash = hash160(
            hex_str_to_bytes(
                self.nodes[0].getaddressinfo(new_address)["pubkey"]))
        colorid1 = b'\xc1' + sha256(hex_str_to_bytes(utxo['scriptPubKey']))
        cp2pkh_address = byte_to_base58(pubkeyhash, colorid1, 112)

        #  create colored transaction 1
        raw_tx_in_block = self.nodes[0].signrawtransactionwithwallet(
            self.nodes[0].createrawtransaction(
                inputs=[{
                    'txid': utxo['txid'],
                    'vout': utxo['vout']
                }],
                outputs=[{
                    self.nodes[1].getnewaddress(): 10
                }, {
                    self.nodes[0].getnewaddress(): 39
                }, {
                    cp2pkh_address: 100
                }],
            ), [], "ALL", self.options.scheme)['hex']
        txid_in_block = self.nodes[0].sendrawtransaction(
            hexstring=raw_tx_in_block, allowhighfees=True)

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

        assert_equal(self.nodes[0].getbalance(), 39)
        assert_equal(self.nodes[1].getbalance(), 10)
        assert_equal(self.nodes[2].getbalance(), 101)

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

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 2)
        assert_equal(walletinfo['balance']['TPC'], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 0)

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

        colorFromNode = self.nodes[0].getcolor(1, utxo['scriptPubKey'])
        assert_equal(hex_str_to_bytes(colorFromNode), colorid1)
        colorFromNode = self.nodes[0].getcolor(2, txid_in_block, 1)
        utxo_ser = sha256(
            reverse_bytes(hex_str_to_bytes(txid_in_block)) +
            (1).to_bytes(4, byteorder='little'))
        coloridexpected = 'c2' + encode(utxo_ser, 'hex_codec').decode('ascii')
        assert_equal(colorFromNode, coloridexpected)

        #  PART 2: using cp2sh address
        utxo = self.nodes[0].listunspent()[0]
        pubkeyhash = hash160(
            hex_str_to_bytes(self.nodes[1].getaddressinfo(
                self.nodes[1].getnewaddress())["pubkey"]))
        scripthash = hash160(
            CScript(
                [OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG]))
        colorid2 = b'\xc1' + sha256(hex_str_to_bytes(utxo['scriptPubKey']))
        cp2sh_address = byte_to_base58(scripthash, colorid2, 197)

        #  create colored transaction 2
        raw_tx_in_block = self.nodes[0].signrawtransactionwithwallet(
            self.nodes[0].createrawtransaction(
                inputs=[{
                    'txid': utxo['txid'],
                    'vout': utxo['vout']
                }],
                outputs=[{
                    self.nodes[1].getnewaddress(): 10
                }, {
                    self.nodes[0].getnewaddress(): 28
                }, {
                    cp2sh_address: 100
                }],
            ), [], "ALL", self.options.scheme)['hex']
        txid_in_block = self.nodes[0].sendrawtransaction(
            hexstring=raw_tx_in_block, allowhighfees=True)

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

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(walletinfo['balance']['TPC'], 28)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 100)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 0)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(walletinfo['balance']['TPC'], 20)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 0)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 100)

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

        colorFromNode = self.nodes[0].getcolor(1, utxo['scriptPubKey'])
        assert_equal(hex_str_to_bytes(colorFromNode), colorid2)
        colorFromNode = self.nodes[0].getcolor(2, txid_in_block, 1)
        utxo_ser = sha256(
            reverse_bytes(hex_str_to_bytes(txid_in_block)) +
            (1).to_bytes(4, byteorder='little'))
        coloridexpected = 'c2' + encode(utxo_ser, 'hex_codec').decode('ascii')
        assert_equal(colorFromNode, coloridexpected)

        # send colored coins  (colorid1) from node0 to node1 using sendtoaddress:
        new_address = self.nodes[1].getnewaddress()
        pubkeyhash = hash160(
            hex_str_to_bytes(
                self.nodes[1].getaddressinfo(new_address)["pubkey"]))
        cp2pkh_address = byte_to_base58(pubkeyhash, colorid1, 112)

        self.log.debug("Testing sendtoaddress")
        txid = self.nodes[0].sendtoaddress(cp2pkh_address, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "token": bytes_to_hex_str(colorid1),
            "amount": -10,
            "confirmations": 0
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "token": bytes_to_hex_str(colorid1),
            "amount": 10,
            "confirmations": 0
        })
        #mine a block, confirmations should change:
        self.nodes[2].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "token": bytes_to_hex_str(colorid1),
            "amount": -10,
            "confirmations": 1
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "token": bytes_to_hex_str(colorid1),
            "amount": 10,
            "confirmations": 1
        })

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '27.99990480')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 90)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 0)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(walletinfo['balance']['TPC'], 20)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 100)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 1)
        assert_equal(str(walletinfo['balance']['TPC']), '202.00009520')

        # send colored coins (colorid2) from node1 to node0 using transfertoken:
        new_address = self.nodes[0].getnewaddress()
        pubkeyhash = hash160(
            hex_str_to_bytes(
                self.nodes[0].getaddressinfo(new_address)["pubkey"]))
        cp2pkh_address = byte_to_base58(pubkeyhash, colorid2, 112)

        self.log.debug("Testing transfertoken")
        txid_transfer = self.nodes[1].transfertoken(cp2pkh_address, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid_transfer}, {
                                "category": "send",
                                "token": bytes_to_hex_str(colorid2),
                                "amount": -10,
                                "confirmations": 0
                            })
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid_transfer}, {
                                "category": "receive",
                                "token": bytes_to_hex_str(colorid2),
                                "amount": 10,
                                "confirmations": 0
                            })
        #mine a block, confirmations should change:
        self.nodes[2].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        assert_array_result(self.nodes[1].listtransactions(),
                            {"txid": txid_transfer}, {
                                "category": "send",
                                "token": bytes_to_hex_str(colorid2),
                                "amount": -10,
                                "confirmations": 1
                            })
        assert_array_result(self.nodes[0].listtransactions(),
                            {"txid": txid_transfer}, {
                                "category": "receive",
                                "token": bytes_to_hex_str(colorid2),
                                "amount": 10,
                                "confirmations": 1
                            })

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '27.99990480')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 90)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 10)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '19.99992080')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 90)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 1)
        assert_equal(str(walletinfo['balance']['TPC']), '252.00017440')

        self.log.debug("Testing getcolor")
        node2_utxos = self.nodes[2].listunspent()
        colorFromNode = self.nodes[2].getcolor(2, node2_utxos[0]['txid'],
                                               node2_utxos[0]['vout'])
        utxo_ser = sha256(
            reverse_bytes(hex_str_to_bytes(node2_utxos[0]['txid'])) +
            (node2_utxos[0]['vout']).to_bytes(4, byteorder='little'))
        colorid3 = 'c2' + encode(utxo_ser, 'hex_codec').decode('ascii')
        assert_equal(colorFromNode, colorid3)

        colorFromNode = self.nodes[2].getcolor(3, node2_utxos[1]['txid'],
                                               node2_utxos[1]['vout'])
        utxo_ser = sha256(
            reverse_bytes(hex_str_to_bytes(node2_utxos[1]['txid'])) +
            (node2_utxos[0]['vout']).to_bytes(4, byteorder='little'))
        colorid4 = 'c3' + encode(utxo_ser, 'hex_codec').decode('ascii')
        assert_equal(colorFromNode, colorid4)

        self.log.debug("Testing issuetoken")
        res = self.nodes[2].issuetoken(2, 100, node2_utxos[0]['txid'],
                                       node2_utxos[0]['vout'])
        txid_issue = res['txid']
        assert_equal(res['color'], colorid3)

        assert_array_result(self.nodes[2].listtransactions(),
                            {"txid": txid_issue}, {
                                "category": "receive",
                                "token": colorid3,
                                "amount": 100,
                                "confirmations": 0
                            })
        #mine a block, confirmations should change:
        self.nodes[2].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        assert_array_result(self.nodes[2].listtransactions(),
                            {"txid": txid_issue}, {
                                "category": "receive",
                                "token": colorid3,
                                "amount": 100,
                                "confirmations": 1
                            })

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '27.99990480')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 90)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 10)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '19.99992080')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 90)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 2)
        assert_equal(str(walletinfo['balance']['TPC']), '302.00017440')
        assert_equal(walletinfo['balance'][colorid3], 100)

        self.log.debug("Testing burntoken")
        txid_burn = self.nodes[1].burntoken(bytes_to_hex_str(colorid2), 20)

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

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '27.99990480')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 90)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 10)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '19.99983940')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 70)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 2)
        assert_equal(str(walletinfo['balance']['TPC']), '352.00017440')
        assert_equal(walletinfo['balance'][colorid3], 100)

        txid_burn = self.nodes[0].burntoken(bytes_to_hex_str(colorid1), 90)

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

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '27.99983720')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 0)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 10)

        walletinfo = self.nodes[1].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 3)
        assert_equal(str(walletinfo['balance']['TPC']), '19.99983940')
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid1)], 10)
        assert_equal(walletinfo['balance'][bytes_to_hex_str(colorid2)], 70)

        walletinfo = self.nodes[2].getwalletinfo()
        assert_equal(len(walletinfo['balance']), 2)
        assert_equal(str(walletinfo['balance']['TPC']), '402.00025580')
        assert_equal(walletinfo['balance'][colorid3], 100)
Beispiel #25
0
    def run_test(self):
        # save the number of coinbase reward addresses so far
        num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(
            minconf=0, include_empty=True, include_watchonly=True))

        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.generate(self.nodes[1], 10)
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr}, {
                                "address": addr,
                                "label": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        # With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr}, {
                                "address": addr,
                                "label": "",
                                "amount": Decimal("0.1"),
                                "confirmations": 10,
                                "txids": [
                                    txid,
                                ]
                            })
        # With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11),
                            {"address": addr}, {}, True)

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

        # Test Address filtering
        # Only on addr
        expected = {
            "address": addr,
            "label": "",
            "amount": Decimal("0.1"),
            "confirmations": 10,
            "txids": [
                txid,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(minconf=0,
                                                  include_empty=True,
                                                  include_watchonly=True,
                                                  address_filter=addr)
        assert_array_result(res, {"address": addr}, expected)
        assert_equal(len(res), 1)
        # Test for regression on CLI calls with address string (#14173)
        cli_res = self.nodes[1].cli.listreceivedbyaddress(0, True, True, addr)
        assert_array_result(cli_res, {"address": addr}, expected)
        assert_equal(len(cli_res), 1)
        # Error on invalid address
        assert_raises_rpc_error(-4,
                                "address_filter parameter was invalid",
                                self.nodes[1].listreceivedbyaddress,
                                minconf=0,
                                include_empty=True,
                                include_watchonly=True,
                                address_filter="bamboozling")
        # Another address receive money
        res = self.nodes[1].listreceivedbyaddress(0, True, True)
        assert_equal(len(res),
                     2 + num_cb_reward_addresses)  # Right now 2 entries
        other_addr = self.nodes[1].getnewaddress()
        txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
        self.generate(self.nodes[0], 1)
        # Same test as above should still pass
        expected = {
            "address": addr,
            "label": "",
            "amount": Decimal("0.1"),
            "confirmations": 11,
            "txids": [
                txid,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(0, 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": "",
            "amount": Decimal("0.1"),
            "confirmations": 1,
            "txids": [
                txid2,
            ]
        }
        res = self.nodes[1].listreceivedbyaddress(0, 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(0, True, True)
        assert_equal(len(res), 3 + num_cb_reward_addresses)  # 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(0, 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].getreceivedbyaddress(addr, 0)
        assert_equal(balance, Decimal("0.1"))

        # Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
        self.generate(self.nodes[1], 10)
        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()
        test_address(self.nodes[1], address, labels=[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.generate(self.nodes[1], 10)
        # listreceivedbylabel should return updated received list
        assert_array_result(
            self.nodes[1].listreceivedbylabel(), {"label": label}, {
                "label": received_by_label_json["label"],
                "amount": (received_by_label_json["amount"] + Decimal("0.1"))
            })

        # getreceivedbylabel should return updated receive total
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance, balance_by_label + 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(0, 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, Decimal("0.0"))

        self.log.info("Tests for including coinbase outputs")

        # Generate block reward to address with label
        label = "label"
        address = self.nodes[0].getnewaddress(label)

        reward = Decimal("25")
        self.generatetoaddress(self.nodes[0], 1, address)
        hash = self.nodes[0].getbestblockhash()

        self.log.info("getreceivedbyaddress returns nothing with defaults")
        balance = self.nodes[0].getreceivedbyaddress(address)
        assert_equal(balance, 0)

        self.log.info(
            "getreceivedbyaddress returns block reward when including immature coinbase"
        )
        balance = self.nodes[0].getreceivedbyaddress(
            address=address, include_immature_coinbase=True)
        assert_equal(balance, reward)

        self.log.info("getreceivedbylabel returns nothing with defaults")
        balance = self.nodes[0].getreceivedbylabel("label")
        assert_equal(balance, 0)

        self.log.info(
            "getreceivedbylabel returns block reward when including immature coinbase"
        )
        balance = self.nodes[0].getreceivedbylabel(
            label="label", include_immature_coinbase=True)
        assert_equal(balance, reward)

        self.log.info(
            "listreceivedbyaddress does not include address with defaults")
        assert_array_result(self.nodes[0].listreceivedbyaddress(),
                            {"address": address}, {}, True)

        self.log.info(
            "listreceivedbyaddress includes address when including immature coinbase"
        )
        assert_array_result(
            self.nodes[0].listreceivedbyaddress(
                minconf=1, include_immature_coinbase=True),
            {"address": address}, {
                "address": address,
                "amount": reward
            })

        self.log.info(
            "listreceivedbylabel does not include label with defaults")
        assert_array_result(self.nodes[0].listreceivedbylabel(),
                            {"label": label}, {}, True)

        self.log.info(
            "listreceivedbylabel includes label when including immature coinbase"
        )
        assert_array_result(
            self.nodes[0].listreceivedbylabel(minconf=1,
                                              include_immature_coinbase=True),
            {"label": label}, {
                "label": label,
                "amount": reward
            })

        self.log.info("Generate 100 more blocks")
        self.generate(self.nodes[0], COINBASE_MATURITY)

        self.log.info("getreceivedbyaddress returns reward with defaults")
        balance = self.nodes[0].getreceivedbyaddress(address)
        assert_equal(balance, reward)

        self.log.info("getreceivedbylabel returns reward with defaults")
        balance = self.nodes[0].getreceivedbylabel("label")
        assert_equal(balance, reward)

        self.log.info("listreceivedbyaddress includes address with defaults")
        assert_array_result(self.nodes[0].listreceivedbyaddress(),
                            {"address": address}, {
                                "address": address,
                                "amount": reward
                            })

        self.log.info("listreceivedbylabel includes label with defaults")
        assert_array_result(self.nodes[0].listreceivedbylabel(),
                            {"label": label}, {
                                "label": label,
                                "amount": reward
                            })

        self.log.info("Invalidate block that paid to address")
        self.nodes[0].invalidateblock(hash)

        self.log.info(
            "getreceivedbyaddress does not include invalidated block when minconf is 0 when including immature coinbase"
        )
        balance = self.nodes[0].getreceivedbyaddress(
            address=address, minconf=0, include_immature_coinbase=True)
        assert_equal(balance, 0)

        self.log.info(
            "getreceivedbylabel does not include invalidated block when minconf is 0 when including immature coinbase"
        )
        balance = self.nodes[0].getreceivedbylabel(
            label="label", minconf=0, include_immature_coinbase=True)
        assert_equal(balance, 0)

        self.log.info(
            "listreceivedbyaddress does not include invalidated block when minconf is 0 when including immature coinbase"
        )
        assert_array_result(
            self.nodes[0].listreceivedbyaddress(
                minconf=0, include_immature_coinbase=True),
            {"address": address}, {}, True)

        self.log.info(
            "listreceivedbylabel does not include invalidated block when minconf is 0 when including immature coinbase"
        )
        assert_array_result(
            self.nodes[0].listreceivedbylabel(minconf=0,
                                              include_immature_coinbase=True),
            {"label": label}, {}, True)

        # Test exclude_coinbase
        address2 = self.nodes[1].getnewaddress(label)
        self.generatetoaddress(self.nodes[1],
                               COINBASE_MATURITY + 1,
                               address2,
                               sync_fun=self.no_op)

        self.log.info(
            "getreceivedbyaddress returns nothing when excluding coinbase")
        balance = self.nodes[1].getreceivedbyaddress(address2)
        assert_equal(balance, 0)

        self.log.info(
            "getreceivedbylabel returns nothing when excluding coinbase")
        balance = self.nodes[1].getreceivedbylabel("label")
        assert_equal(balance, 0)

        self.log.info(
            "listreceivedbyaddress does not include address when excluding coinbase"
        )
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": address2}, {}, True)

        self.log.info(
            "listreceivedbylabel does not include label when excluding coinbase"
        )
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"label": label}, {}, True)

        self.log.info(
            "getreceivedbyaddress throws when setting include_immature_coinbase with deprecated exclude_coinbase"
        )
        assert_raises_rpc_error(
            -8,
            'include_immature_coinbase is incompatible with deprecated exclude_coinbase',
            self.nodes[1].getreceivedbyaddress, address2, 1, True)

        self.log.info(
            "listreceivedbyaddress throws when setting include_immature_coinbase with deprecated exclude_coinbase"
        )
        assert_raises_rpc_error(
            -8,
            'include_immature_coinbase is incompatible with deprecated exclude_coinbase',
            self.nodes[1].listreceivedbyaddress, 1, False, False, "", True)
Beispiel #26
0
    def test_sendRPC(self, rpcname):
        self.log.info("Testing %s" % rpcname)

        #pubkeyhash and script hash for colored addresses on node 1
        new_address = self.nodes[1].getnewaddress()
        pubkeyhash = hash160(
            hex_str_to_bytes(
                self.nodes[1].getaddressinfo(new_address)["pubkey"]))
        scripthash = hash160(
            CScript(
                [OP_DUP, OP_HASH160, pubkeyhash, OP_EQUALVERIFY, OP_CHECKSIG]))

        cp2pkh_address1 = byte_to_base58(pubkeyhash,
                                         hex_str_to_bytes(self.colorids[1]),
                                         112)
        cp2sh_address1 = byte_to_base58(scripthash,
                                        hex_str_to_bytes(self.colorids[1]),
                                        197)

        cp2pkh_address2 = byte_to_base58(pubkeyhash,
                                         hex_str_to_bytes(self.colorids[2]),
                                         112)
        cp2pkh_address3 = byte_to_base58(pubkeyhash,
                                         hex_str_to_bytes(self.colorids[3]),
                                         112)

        cp2sh_address4 = byte_to_base58(scripthash,
                                        hex_str_to_bytes(self.colorids[4]),
                                        197)
        cp2sh_address5 = byte_to_base58(scripthash,
                                        hex_str_to_bytes(self.colorids[5]),
                                        197)

        sendrpc = getattr(self.nodes[0], rpcname,
                          lambda x: print("no method %s" % x))
        txid1 = sendrpc(cp2pkh_address1, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid1},
                            {
                                "category": "send",
                                "token": self.colorids[1],
                                "amount": -10,
                                "confirmations": 0
                            })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid1},
                            {
                                "category": "receive",
                                "token": self.colorids[1],
                                "amount": 10,
                                "confirmations": 0
                            })

        txid2 = sendrpc(cp2sh_address1, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid2},
                            {
                                "category": "send",
                                "token": self.colorids[1],
                                "amount": -10,
                                "confirmations": 0
                            })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid2},
                            {
                                "category": "receive",
                                "token": self.colorids[1],
                                "amount": 10,
                                "confirmations": 0
                            })

        txid3 = sendrpc(cp2pkh_address2, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid3},
                            {
                                "category": "send",
                                "token": self.colorids[2],
                                "amount": -10,
                                "confirmations": 0
                            })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid3},
                            {
                                "category": "receive",
                                "token": self.colorids[2],
                                "amount": 10,
                                "confirmations": 0
                            })

        #NFT can be transferred only once. so call it only the first time
        if (rpcname == "sendtoaddress"):
            txid4 = sendrpc(cp2pkh_address3, 1)
            self.sync_all([self.nodes[0:3]])

            assert_array_result(self.nodes[0].listtransactions(),
                                {"txid": txid4}, {
                                    "category": "send",
                                    "token": self.colorids[3],
                                    "amount": -1,
                                    "confirmations": 0
                                })
            assert_array_result(self.nodes[1].listtransactions(),
                                {"txid": txid4}, {
                                    "category": "receive",
                                    "token": self.colorids[3],
                                    "amount": 1,
                                    "confirmations": 0
                                })

        txid5 = sendrpc(cp2sh_address4, 10)
        self.sync_all([self.nodes[0:3]])

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid5},
                            {
                                "category": "send",
                                "token": self.colorids[4],
                                "amount": -10,
                                "confirmations": 0
                            })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid5},
                            {
                                "category": "receive",
                                "token": self.colorids[4],
                                "amount": 10,
                                "confirmations": 0
                            })

        #NFT can be transferred only once. so call it only the first time
        if (rpcname == "sendtoaddress"):
            txid6 = sendrpc(cp2sh_address5, 1)
            self.sync_all([self.nodes[0:3]])

            assert_array_result(self.nodes[0].listtransactions(),
                                {"txid": txid6}, {
                                    "category": "send",
                                    "token": self.colorids[5],
                                    "amount": -1,
                                    "confirmations": 0
                                })
            assert_array_result(self.nodes[1].listtransactions(),
                                {"txid": txid6}, {
                                    "category": "receive",
                                    "token": self.colorids[5],
                                    "amount": 1,
                                    "confirmations": 0
                                })
        #mine a block, confirmations should change:
        self.nodes[2].generate(1, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:3]])
        unspent = self.nodes[0].listunspent()
        assert_array_result(unspent, {
            "txid": txid1,
            "token": self.colorids[1]
        }, {
            "amount": self.balance_expected[0][self.stage][3],
            "confirmations": 1
        })
        assert_array_result(unspent, {
            "txid": txid2,
            "token": self.colorids[1]
        }, {
            "amount": self.balance_expected[0][self.stage][3],
            "confirmations": 1
        })
        assert_array_result(unspent, {
            "txid": txid3,
            "token": self.colorids[2]
        }, {
            "amount": self.balance_expected[0][self.stage][5],
            "confirmations": 1
        })
        assert_array_result(unspent, {
            "txid": txid5,
            "token": self.colorids[4]
        }, {
            "amount": self.balance_expected[0][self.stage][5],
            "confirmations": 1
        })

        txlist = self.nodes[0].listtransactions()
        assert_array_result(txlist, {"txid": txid1}, {"confirmations": 1})
        assert_array_result(txlist, {"txid": txid2}, {"confirmations": 1})
        assert_array_result(txlist, {"txid": txid3}, {"confirmations": 1})
        assert_array_result(txlist, {"txid": txid5}, {"confirmations": 1})

        if (rpcname == "sendtoaddress"):
            assert_array_result(txlist, {"txid": txid4}, {"confirmations": 1})
            assert_array_result(txlist, {"txid": txid6}, {"confirmations": 1})
            unspent = self.nodes[1].listunspent()
            assert_array_result(unspent, {
                "txid": txid4,
                "token": self.colorids[3]
            }, {
                "amount": 1,
                "confirmations": 1
            })
            assert_array_result(unspent, {
                "txid": txid6,
                "token": self.colorids[5]
            }, {
                "amount": 1,
                "confirmations": 1
            })
        self.test_nodeBalances()

        #negative
        if not self.options.usecli:
            assert_raises_rpc_error(-3, "Invalid amount", sendrpc,
                                    cp2pkh_address1, 'foo')
            assert_raises_rpc_error(-3, "Invalid amount", sendrpc,
                                    cp2pkh_address1, '66ae')
            assert_raises_rpc_error(-3, "Invalid amount", sendrpc,
                                    cp2pkh_address1, 66.99)
Beispiel #27
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)

        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 50)
        assert_equal(walletinfo['balance'], 0)

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

        assert_equal(self.nodes[0].getbalance(), 50)
        assert_equal(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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[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(txout['value'], 50)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 50)

        # Send 21 BTC from 0 to 2 using sendtoaddress call.
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)

        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(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_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 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(set([txout1['value'], txout2['value']]), set([10, balance]))
        walletinfo = self.nodes[0].getwalletinfo()
        assert_equal(walletinfo['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        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, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
        assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
                                self.nodes[2].lockunspent, False,
                                [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "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)["hex"]
        self.nodes[1].sendrawtransaction(tx)
        assert_equal(len(self.nodes[1].listlockunspent()), 0)

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

        # node0 should end up with 100 btc in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 100 - 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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            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))

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

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

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

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

        # Send 10 BTC 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)
        self.nodes[2].generate(1)
        self.sync_all(self.nodes[0:3])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))

        # Sendmany 10 BTC
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 BTC with subtract fee from amount
        txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
        self.nodes[2].generate(1)
        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].gettransaction(txid)['hex']))

        self.start_node(3)
        connect_nodes_bi(self.nodes, 0, 3)
        self.sync_all()

        # 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)
        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'])

        self.sync_all()
        self.nodes[1].generate(1)  # 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)  # 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.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)
        self.sync_blocks(self.nodes[0:3])

        self.nodes[0].generate(1)
        self.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'))

        # General checks for errors from incorrect inputs
        # 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")

        # This will raise an exception for the invalid private key format
        assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")

        # This will raise an exception for importing an address with the PS2H flag
        temp_address = self.nodes[1].getnewaddress()
        assert_raises_rpc_error(-5, "Cannot use the p2sh flag with an address - use a script instead", self.nodes[0].importaddress, temp_address, "label", False, True)

        # This will raise an exception for attempting to dump the private key of an address you do not own
        assert_raises_rpc_error(-4, "Private key for address", self.nodes[0].dumpprivkey, temp_address)

        # This will raise an exception for attempting to get the private key of an invalid Bitcoin address
        assert_raises_rpc_error(-5, "Invalid Namecoin address", self.nodes[0].dumpprivkey, "invalid")

        # This will raise an exception for attempting to set a label for an invalid Bitcoin address
        assert_raises_rpc_error(-5, "Invalid Namecoin address", self.nodes[0].setlabel, "invalid address", "label")

        # This will raise an exception for importing an invalid address
        assert_raises_rpc_error(-5, "Invalid Namecoin address or script", self.nodes[0].importaddress, "invalid")

        # This will raise an exception for attempting to import a pubkey that isn't in hex
        assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex")

        # This will raise an exception for importing an invalid pubkey
        assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f")

        # 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.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)[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.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)
        self.nodes[0].generate(1)
        node0_balance = self.nodes[0].getbalance()
        # 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)
        singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)

        # 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 * 2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
        assert_equal(len(txid_list), chainlimit * 2)

        # 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 * 2):
            time.sleep(0.5)
            timeout -= 0.5
        assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)

        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 on external address. 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"]
        assert not address_info["ischange"]

        # Test getaddressinfo 'ischange' field on change address.
        self.nodes[0].generate(1)
        destination = self.nodes[1].getnewaddress()
        txid = self.nodes[0].sendtoaddress(destination, 0.123)
        tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex'])
        output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
        assert len(output_addresses) > 1
        for address in output_addresses:
            ischange = self.nodes[0].getaddressinfo(address)['ischange']
            assert_equal(ischange, address != destination)
            if ischange:
                change = address
        self.nodes[0].setlabel(change, 'foobar')
        assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)
Beispiel #28
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)

        wallet_info = self.nodes[0].getwalletinfo()
        assert_equal(wallet_info['immature_balance'], 5000)
        assert_equal(wallet_info['balance'], 0)

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

        assert_equal(self.nodes[0].getbalance(), 5000)
        assert_equal(self.nodes[1].getbalance(), 5000)
        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), 1)
        assert_equal(len(self.nodes[1].listunspent()), 1)
        assert_equal(len(self.nodes[2].listunspent()), 0)

        self.log.info("test gettxout")
        confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[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(txout['value'], 5000)
        txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
        assert_equal(txout['value'], 5000)
        
        # Send 21 FOXD 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()
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
        mempool_txid = 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(txout['value'], 5000)
        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_txid, 0, False)
        assert txout is None
        txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
        txout2 = self.nodes[0].gettxout(mempool_txid, 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']}, {10, balance})
        wallet_info = self.nodes[0].getwalletinfo()
        assert_equal(wallet_info['immature_balance'], 0)

        # Have node0 mine a block, thus it will collect its own fee.
        self.nodes[0].generate(1)
        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"]}
        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)

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

        # node0 should end up with 100 btc in block rewards plus fees, but
        # minus the 21 plus fees sent to node2
        assert_equal(self.nodes[0].getbalance(), 10000-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), 2)

        # create both transactions
        txns_to_send = []
        for utxo in node0utxos:
            inputs = []
            outputs = {}
            inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
            outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] - 3
            raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
            txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))

        # 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)

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

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 9994)
        assert_equal(self.nodes[2].getbalance("from1"), 9994-21)

        # Send 10 FOXD 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)
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('9984'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
        assert_equal(self.nodes[0].getbalance(), Decimal('10'))

        # Send 10 FOXD with subtract fee from amount
        txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
        self.nodes[2].generate(1)
        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, count_bytes(self.nodes[2].getrawtransaction(txid)))

        # Sendmany 10 FOXD
        txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [])
        self.nodes[2].generate(1)
        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, count_bytes(self.nodes[2].getrawtransaction(txid)))
        assert_equal(self.nodes[0].getbalance(), node_0_bal)

        # Sendmany 10 FOXD with subtract fee from amount
        txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [address])
        self.nodes[2].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal -= Decimal('10')
        assert_equal(self.nodes[2].getbalance(), node_2_bal)
        self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, count_bytes(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.start_node(3)
        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"], 1)
        assert_equal(self.nodes[0].getunconfirmedbalance(), 1)

        #check if we can list zero value tx as available coins
        #1. create rawtx
        #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()
        inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}]
        outputs = {self.nodes[1].getnewaddress(): 4999.998, self.nodes[0].getnewaddress(): 1111.11}

        raw_tx = self.nodes[1].createrawtransaction(inputs, outputs)
        raw_tx = raw_tx.replace("c04fbbde19", "0000000000") #replace 1111.11 with 0.0 (int32)
        self.nodes[1].decoderawtransaction(raw_tx)
        signed_raw_tx = self.nodes[1].signrawtransaction(raw_tx)
        dec_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
        zero_value_txid = dec_raw_tx['txid']
        self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])

        self.sync_all()
        self.nodes[1].generate(1) #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]])

        tx_id_not_broadcasted  = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
        tx_obj_not_broadcasted = self.nodes[0].gettransaction(tx_id_not_broadcasted)
        self.nodes[1].generate(1) #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_broadcasted['hex'])
        self.nodes[1].generate(1)
        self.sync_all([self.nodes[0:3]])
        node_2_bal += 2
        self.nodes[0].gettransaction(tx_id_not_broadcasted)
        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)
        sync_blocks(self.nodes[0:3])
        node_2_bal += 2

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

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

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

        #check if JSON parser can handle scientific notation in strings
        tx_id  = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
        tx_obj = self.nodes[0].gettransaction(tx_id)
        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")

        # 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()
        self.nodes[0].sendtoaddress(address_to_import, 1)
        self.nodes[0].generate(1)
        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].validateaddress(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
        cb_address = self.nodes[1].getnewaddress()
        block_hash = self.nodes[0].generatetoaddress(1, cb_address)[0]
        cb_tx_id = 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(cb_tx_id)

        # check if wallet or blockchain maintenance changes the balance
        self.sync_all([self.nodes[0:3]])
        blocks = self.nodes[0].generate(2)
        self.sync_all([self.nodes[0:3]])
        balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
        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].ensure_ascii = mode
            # unicode check: Basic Multilingual Plane, Supplementary Plane respectively
            for s in [u'б€б‹аБаА', u'№…Ё']:
                addr = self.nodes[0].getaccountaddress(s)
                label = self.nodes[0].getaccount(addr)
                assert_equal(label, s)
                assert(s in self.nodes[0].listaccounts().keys())
        self.nodes[0].ensure_ascii = True # restore to default

        # maintenance tests
        maintenance = "-rescan -reindex -zapwallettxes=1 -zapwallettxes=2"
        chain_limit = 6
        self.log.info("check " + maintenance)
        self.stop_nodes()
        # set lower ancestor limit for later
        self.start_node(0, [maintenance, "-limitancestorcount="+str(chain_limit)])
        self.start_node(1, [maintenance, "-limitancestorcount="+str(chain_limit)])
        self.start_node(2, [maintenance, "-limitancestorcount="+str(chain_limit)])
        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()]
        single_tx_id = self.nodes[0].sendtoaddress(chain_addrs[0], self.nodes[0].getbalance(), "", "", True)
        self.nodes[0].generate(1)
        node0_balance = self.nodes[0].getbalance()
        # Split into two chains
        rawtx = self.nodes[0].createrawtransaction([{"txid":single_tx_id, "vout":0}], {chain_addrs[0]:node0_balance/2-Decimal('0.01'), chain_addrs[1]:node0_balance/2-Decimal('0.01')})
        signedtx = self.nodes[0].signrawtransaction(rawtx)
        self.nodes[0].sendrawtransaction(signedtx["hex"])
        self.nodes[0].generate(1)

        # 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 _ in range(chain_limit*2):
            txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
        assert_equal(self.nodes[0].getmempoolinfo()['size'], chain_limit*2)
        assert_equal(len(txid_list), chain_limit*2)

        # Without walletrejectlongchains, we will still generate a txid
        # The tx will be stored in the wallet but not accepted to the mempool
        assert_raises_rpc_error(-4, "Error: The transaction was rejected! Reason given: too-long-mempool-chain", self.nodes[0].sendtoaddress, sending_addr, Decimal('0.0001'))
        # Get the last transaction and verify it is not in the mempool
        trans_count = len(self.nodes[0].listtransactions("*",99999))
        extra_txid = (self.nodes[0].listtransactions("*",1, trans_count-1))[0]['txid']
        assert(extra_txid not in self.nodes[0].getrawmempool())
        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*chain_limit)])

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

        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)))
    def run_rbf_opt_in_test(self):
        # Check whether a transaction signals opt-in RBF itself
        def is_opt_in(node, txid):
            rawtx = node.getrawtransaction(txid, 1)
            for x in rawtx["vin"]:
                if x["sequence"] < 0xfffffffe:
                    return True
            return False

        # Find an unconfirmed output matching a certain txid
        def get_unconfirmed_utxo_entry(node, txid_to_match):
            utxo = node.listunspent(0, 0)
            for i in utxo:
                if i["txid"] == txid_to_match:
                    return i
            return None

        # 1. Chain a few transactions that don't opt-in.
        txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        assert not is_opt_in(self.nodes[0], txid_1)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})

        # Tx2 will build off txid_1, still not opting in to RBF.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1)
        assert_equal(utxo_to_use["safe"], True)
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
        assert_equal(utxo_to_use["safe"], False)

        # Create tx2 using createrawtransaction
        inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.999}
        tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
        txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)

        # ...and check the result
        assert not is_opt_in(self.nodes[1], txid_2)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})

        # Tx3 will opt-in to RBF
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
        inputs = [{"txid": txid_2, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[1].getnewaddress(): 0.998}
        tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
        tx3_modified = tx_from_hex(tx3)
        tx3_modified.vin[0].nSequence = 0
        tx3 = tx3_modified.serialize().hex()
        tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex']
        txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)

        assert is_opt_in(self.nodes[0], txid_3)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})

        # Tx4 will chain off tx3.  Doesn't signal itself, but depends on one
        # that does.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
        inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.997}
        tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
        txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)

        assert not is_opt_in(self.nodes[1], txid_4)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})

        # Replace tx3, and check that tx4 becomes unknown
        tx3_b = tx3_modified
        tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN)  # bump the fee
        tx3_b = tx3_b.serialize().hex()
        tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex']
        txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
        assert is_opt_in(self.nodes[0], txid_3b)

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})
        sync_mempools(self.nodes)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})

        # Check gettransaction as well:
        for n in self.nodes[0:2]:
            assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
            assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
            assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown")

        # After mining a transaction, it's no longer BIP125-replaceable
        self.nodes[0].generate(1)
        assert txid_3b not in self.nodes[0].getrawmempool()
        assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
        assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
    def run_test(self):
        self.nodes[0].generate(1)  # Get out of IBD
        self.sync_all()
        # Simple send, 0 to 1:
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 0
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 0
        })
        # mine a block, confirmations should change:
        blockhash = self.nodes[0].generate(1)[0]
        blockheight = self.nodes[0].getblockheader(blockhash)['height']
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 1,
            "blockhash": blockhash,
            "blockheight": blockheight
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 1,
            "blockhash": blockhash,
            "blockheight": blockheight
        })

        # send-to-self:
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "send"
        }, {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "receive"
        }, {"amount": Decimal("0.2")})

        # sendmany from node1: twice to self, twice to node2:
        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getnewaddress(): 0.33,
            self.nodes[1].getnewaddress(): 0.44
        }
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.44")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.44")
        }, {"txid": txid})

        if not self.options.descriptors:
            # include_watchonly is a legacy wallet feature, so don't test it for descriptor wallets
            pubkey = self.nodes[1].getaddressinfo(
                self.nodes[1].getnewaddress())['pubkey']
            multisig = self.nodes[1].createmultisig(1, [pubkey])
            self.nodes[0].importaddress(multisig["redeemScript"], "watchonly",
                                        False, True)
            txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
            self.nodes[1].generate(1)
            self.sync_all()
            assert_equal(
                len(self.nodes[0].listtransactions(label="watchonly",
                                                   include_watchonly=True)), 1)
            assert_equal(
                len(self.nodes[0].listtransactions(dummy="watchonly",
                                                   include_watchonly=True)), 1)
            assert len(self.nodes[0].listtransactions(
                label="watchonly", count=100, include_watchonly=False)) == 0
            assert_array_result(
                self.nodes[0].listtransactions(label="watchonly",
                                               count=100,
                                               include_watchonly=True), {
                                                   "category": "receive",
                                                   "amount": Decimal("0.1")
                                               }, {
                                                   "txid": txid,
                                                   "label": "watchonly"
                                               })

        self.run_rbf_opt_in_test()
    def run_test(self):
        # Generate block to get out of IBD
        self.nodes[0].generate(1)
        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.sync_all()
        assert_array_result(self.nodes[1].listreceivedbyaddress(),
                            {"address": addr},
                            {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence < 10
        assert_array_result(self.nodes[1].listreceivedbyaddress(5),
                            {"address": addr},
                            {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]})
        # With min confidence > 10, should not find Tx
        assert_array_result(self.nodes[1].listreceivedbyaddress(11), {"address": addr}, {}, True)

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

        # Test Address filtering
        # Only on addr
        expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
        res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
        assert_array_result(res, {"address": addr}, expected)
        assert_equal(len(res), 1)
        # Test for regression on CLI calls with address string (#14173)
        cli_res = self.nodes[1].cli.listreceivedbyaddress(0, True, True, addr)
        assert_array_result(cli_res, {"address": addr}, expected)
        assert_equal(len(cli_res), 1)
        # Error on invalid address
        assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling")
        # Another address receive money
        res = self.nodes[1].listreceivedbyaddress(0, True, True)
        assert_equal(len(res), 2 + self.num_cb_reward_addresses)  # 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.sync_all()
        # Same test as above should still pass
        expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 11, "txids": [txid, ]}
        res = self.nodes[1].listreceivedbyaddress(0, 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": "", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]}
        res = self.nodes[1].listreceivedbyaddress(0, 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(0, True, True)
        assert_equal(len(res), 3 + self.num_cb_reward_addresses)  # 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(0, 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].getreceivedbyaddress(addr, 0)
        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.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.sync_all()
        # listreceivedbylabel should return updated received list
        assert_array_result(self.nodes[1].listreceivedbylabel(),
                            {"label": label},
                            {"label": received_by_label_json["label"], "amount": (received_by_label_json["amount"] + Decimal("0.1"))})

        # getreceivedbylabel should return updated receive total
        balance = self.nodes[1].getreceivedbylabel(label)
        assert_equal(balance, balance_by_label + 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(0, 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, Decimal("0.0"))
Beispiel #32
0
    def run_rbf_opt_in_test(self):
        """Test the opt-in-rbf flag for sent and received transactions."""
        def is_opt_in(node, txid):
            """Check whether a transaction signals opt-in RBF itself."""
            rawtx = node.getrawtransaction(txid, 1)
            for x in rawtx["vin"]:
                if x["sequence"] < 0xfffffffe:
                    return True
            return False

        def get_unconfirmed_utxo_entry(node, txid_to_match):
            """Find an unconfirmed output matching a certain txid."""
            utxo = node.listunspent(0, 0)
            for i in utxo:
                if i["txid"] == txid_to_match:
                    return i
            return None

        self.log.info("Test txs w/o opt-in RBF (bip125-replaceable=no)")
        # Chain a few transactions that don't opt in.
        txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
        assert not is_opt_in(self.nodes[0], txid_1)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1},
                            {"bip125-replaceable": "no"})
        self.sync_mempools()
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1},
                            {"bip125-replaceable": "no"})

        # Tx2 will build off tx1, still not opting in to RBF.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1)
        assert_equal(utxo_to_use["safe"], True)
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
        assert_equal(utxo_to_use["safe"], False)

        # Create tx2 using createrawtransaction
        inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.999}
        tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
        txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)

        # ...and check the result
        assert not is_opt_in(self.nodes[1], txid_2)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2},
                            {"bip125-replaceable": "no"})
        self.sync_mempools()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2},
                            {"bip125-replaceable": "no"})

        self.log.info("Test txs with opt-in RBF (bip125-replaceable=yes)")
        # Tx3 will opt-in to RBF
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
        inputs = [{"txid": txid_2, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[1].getnewaddress(): 0.998}
        tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
        tx3_modified = tx_from_hex(tx3)
        tx3_modified.vin[0].nSequence = 0
        tx3 = tx3_modified.serialize().hex()
        tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex']
        txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)

        assert is_opt_in(self.nodes[0], txid_3)
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3},
                            {"bip125-replaceable": "yes"})
        self.sync_mempools()
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3},
                            {"bip125-replaceable": "yes"})

        # Tx4 will chain off tx3.  Doesn't signal itself, but depends on one
        # that does.
        utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
        inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
        outputs = {self.nodes[0].getnewaddress(): 0.997}
        tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
        tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
        txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)

        assert not is_opt_in(self.nodes[1], txid_4)
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "yes"})
        self.sync_mempools()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "yes"})

        self.log.info(
            "Test tx with unknown RBF state (bip125-replaceable=unknown)")
        # Replace tx3, and check that tx4 becomes unknown
        tx3_b = tx3_modified
        tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN)  # bump the fee
        tx3_b = tx3_b.serialize().hex()
        tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex']
        txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, 0)
        assert is_opt_in(self.nodes[0], txid_3b)

        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "unknown"})
        self.sync_mempools()
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4},
                            {"bip125-replaceable": "unknown"})

        self.log.info("Test bip125-replaceable status with gettransaction RPC")
        for n in self.nodes[0:2]:
            assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
            assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
            assert_equal(
                n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
            assert_equal(
                n.gettransaction(txid_4)["bip125-replaceable"], "unknown")

        self.log.info("Test bip125-replaceable status with listsinceblock")
        for n in self.nodes[0:2]:
            txs = {
                tx['txid']: tx['bip125-replaceable']
                for tx in n.listsinceblock()['transactions']
            }
            assert_equal(txs[txid_1], "no")
            assert_equal(txs[txid_2], "no")
            assert_equal(txs[txid_3], "yes")
            assert_equal(txs[txid_3b], "yes")
            assert_equal(txs[txid_4], "unknown")

        self.log.info(
            "Test mined transactions are no longer bip125-replaceable")
        self.generate(self.nodes[0], 1, sync_fun=self.no_op)
        assert txid_3b not in self.nodes[0].getrawmempool()
        assert_equal(
            self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
        assert_equal(
            self.nodes[0].gettransaction(txid_4)["bip125-replaceable"],
            "unknown")
Beispiel #33
0
    def run_test(self):
        self.log.info("Test simple send from node0 to node1")
        txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
        self.sync_all()
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 0,
            "trusted": True
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 0,
            "trusted": False
        })
        self.log.info("Test confirmations change after mining a block")
        blockhash = self.generate(self.nodes[0], 1)[0]
        blockheight = self.nodes[0].getblockheader(blockhash)['height']
        assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {
            "category": "send",
            "amount": Decimal("-0.1"),
            "confirmations": 1,
            "blockhash": blockhash,
            "blockheight": blockheight
        })
        assert_array_result(self.nodes[1].listtransactions(), {"txid": txid}, {
            "category": "receive",
            "amount": Decimal("0.1"),
            "confirmations": 1,
            "blockhash": blockhash,
            "blockheight": blockheight
        })

        self.log.info("Test send-to-self on node0")
        txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "send"
        }, {"amount": Decimal("-0.2")})
        assert_array_result(self.nodes[0].listtransactions(), {
            "txid": txid,
            "category": "receive"
        }, {"amount": Decimal("0.2")})

        self.log.info(
            "Test sendmany from node1: twice to self, twice to node0")
        send_to = {
            self.nodes[0].getnewaddress(): 0.11,
            self.nodes[1].getnewaddress(): 0.22,
            self.nodes[0].getnewaddress(): 0.33,
            self.nodes[1].getnewaddress(): 0.44
        }
        txid = self.nodes[1].sendmany("", send_to)
        self.sync_all()
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.11")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.22")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[0].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.33")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "send",
            "amount": Decimal("-0.44")
        }, {"txid": txid})
        assert_array_result(self.nodes[1].listtransactions(), {
            "category": "receive",
            "amount": Decimal("0.44")
        }, {"txid": txid})

        if not self.options.descriptors:
            # include_watchonly is a legacy wallet feature, so don't test it for descriptor wallets
            self.log.info("Test 'include_watchonly' feature (legacy wallet)")
            pubkey = self.nodes[1].getaddressinfo(
                self.nodes[1].getnewaddress())['pubkey']
            # SYSCOIN
            multisig = self.nodes[1].createmultisig(1, [pubkey], 'legacy')
            self.nodes[0].importaddress(multisig["redeemScript"], "watchonly",
                                        False, True)
            txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
            self.generate(self.nodes[1], 1)
            assert_equal(
                len(self.nodes[0].listtransactions(label="watchonly",
                                                   include_watchonly=True)), 1)
            assert_equal(
                len(self.nodes[0].listtransactions(dummy="watchonly",
                                                   include_watchonly=True)), 1)
            assert len(self.nodes[0].listtransactions(
                label="watchonly", count=100, include_watchonly=False)) == 0
            assert_array_result(
                self.nodes[0].listtransactions(label="watchonly",
                                               count=100,
                                               include_watchonly=True), {
                                                   "category": "receive",
                                                   "amount": Decimal("0.1")
                                               }, {
                                                   "txid": txid,
                                                   "label": "watchonly"
                                               })

        self.run_rbf_opt_in_test()
Beispiel #34
0
    def run_test(self):
        addr0 = self.nodes[0].getnewaddress("")
        addr1 = self.nodes[0].getnewaddress("")
        addr2 = self.nodes[0].getnewaddress("")
        '''
        generate some test coin
        '''
        self.nodes[0].generatetoaddress(101, addr0)
        # burn 3 BCH
        self.nodes[0].whc_burnbchgetwhc(6)
        self.nodes[0].generatetoaddress(1, addr0)
        self.nodes[0].sendtoaddress(addr1, 3)
        self.nodes[0].sendtoaddress(addr2, 3)
        self.nodes[0].generatetoaddress(1, addr0)
        self.nodes[0].whc_send(addr0, addr1, 1, "300")
        self.nodes[0].whc_send(addr0, addr2, 1, "300")
        self.nodes[0].generatetoaddress(1, addr0)

        # check initial value
        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr1),
                            {"propertyid": 1}, {
                                "balance": "300.00000000",
                                "reserved": "0.00000000"
                            })

        deadline = int(time.mktime(
            datetime.datetime.now().timetuple())) + 86400
        tx = self.nodes[0].whc_sendissuancecrowdsale(
            addr1, 1, 3, 0, "reg crowdsale test", "crowdsale test", "reqcrowd",
            "http://www.google.ca", "crowdsale test data", 1, "100000000",
            deadline, 10, 0, "10000000000")
        self.nodes[0].generatetoaddress(1, addr1)

        # check valid transaction
        ret = self.nodes[0].whc_gettransaction(tx)
        assert ret["valid"] is True
        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr1),
                            {"propertyid": 1}, {
                                "balance": "299.00000000",
                                "reserved": "0.00000000"
                            })

        ret = self.nodes[0].whc_gettransaction(tx)
        ppid = ret["propertyid"]

        # check data
        ret = self.nodes[0].whc_getcrowdsale(ppid)
        assert ret["issuer"] == addr1 and \
               ret["tokensperunit"] == "100000000.00000000"\
               and ret["earlybonus"] == 10 and\
               ret["tokensissued"] == "10000000000.000"

        # test participate crowdsale
        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr1),
                            {"propertyid": 1}, {
                                "balance": "299.00000000",
                                "reserved": "0.00000000"
                            })
        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr2),
                            {"propertyid": 1}, {
                                "balance": "300.00000000",
                                "reserved": "0.00000000"
                            })
        tx = self.nodes[0].whc_particrowsale(addr2, addr1, "31.12")
        self.nodes[0].generatetoaddress(1, addr1)

        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr1),
                            {"propertyid": 1}, {
                                "balance": "330.12000000",
                                "reserved": "0.00000000"
                            })
        assert_array_result(self.nodes[0].whc_getallbalancesforaddress(addr2),
                            {"propertyid": 1}, {
                                "balance": "268.88000000",
                                "reserved": "0.00000000"
                            })