wallet_basic.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2014-2022 The Limenka developers
   3  # Distributed under the MIT software license, see the accompanying
   4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  """Test the wallet."""
   6  from decimal import Decimal
   7  from itertools import product
   8  
   9  from test_framework.blocktools import COINBASE_MATURITY
  10  from test_framework.descriptors import descsum_create
  11  from test_framework.messages import (
  12      COIN,
  13      DEFAULT_ANCESTOR_LIMIT,
  14  )
  15  from test_framework.test_framework import LimenkaTestFramework
  16  from test_framework.util import (
  17      assert_array_result,
  18      assert_equal,
  19      assert_fee_amount,
  20      assert_raises_rpc_error,
  21  )
  22  from test_framework.wallet_util import test_address
  23  from test_framework.wallet import MiniWallet
  24  
  25  NOT_A_NUMBER_OR_STRING = "Amount is not a number or string"
  26  OUT_OF_RANGE = "Amount out of range"
  27  
  28  
  29  class WalletTest(LimenkaTestFramework):
  30      def add_options(self, parser):
  31          self.add_wallet_options(parser)
  32  
  33      def set_test_params(self):
  34          self.num_nodes = 4
  35          # whitelist peers to speed up tx relay / mempool sync
  36          self.noban_tx_relay = True
  37          self.extra_args = [[
  38              "-dustrelayfee=0", "-walletrejectlongchains=0"
  39          ]] * self.num_nodes
  40          self.setup_clean_chain = True
  41          self.supports_cli = False
  42  
  43      def skip_test_if_missing_module(self):
  44          self.skip_if_no_wallet()
  45  
  46      def setup_network(self):
  47          self.setup_nodes()
  48          # Only need nodes 0-2 running at start of test
  49          self.stop_node(3)
  50          self.connect_nodes(0, 1)
  51          self.connect_nodes(1, 2)
  52          self.connect_nodes(0, 2)
  53          self.sync_all(self.nodes[0:3])
  54  
  55      def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
  56          """Return curr_balance after asserting the fee was in range"""
  57          fee = balance_with_fee - curr_balance
  58          assert_fee_amount(fee, tx_size, fee_per_byte * 1000)
  59          return curr_balance
  60  
  61      def get_vsize(self, txn):
  62          return self.nodes[0].decoderawtransaction(txn)['vsize']
  63  
  64      def test_legacy_importaddress(self):
  65          if self.options.descriptors:
  66              return
  67  
  68          addr = self.nodes[1].getnewaddress()
  69          self.nodes[1].sendtoaddress(addr, 10)
  70          self.sync_mempools(self.nodes[0:2])
  71  
  72          self.log.info("Test 'importaddress' on a blank, private keys disabled, wallet with no descriptors support")
  73          self.nodes[0].createwallet(wallet_name="watch-only-legacy", disable_private_keys=False, descriptors=False, blank=True)
  74          wallet_watch_only = self.nodes[0].get_wallet_rpc("watch-only-legacy")
  75          wallet_watch_only.importaddress(addr)
  76          assert_equal(wallet_watch_only.getaddressinfo(addr)['ismine'], False)
  77          assert_equal(wallet_watch_only.getaddressinfo(addr)['iswatchonly'], True)
  78          assert_equal(wallet_watch_only.getaddressinfo(addr)['solvable'], False)
  79          assert_equal(wallet_watch_only.getbalances()["watchonly"]['untrusted_pending'], 10)
  80          self.nodes[0].unloadwallet("watch-only-legacy")
  81  
  82      def run_test(self):
  83  
  84          # Check that there's no UTXO on none of the nodes
  85          assert_equal(len(self.nodes[0].listunspent()), 0)
  86          assert_equal(len(self.nodes[1].listunspent()), 0)
  87          assert_equal(len(self.nodes[2].listunspent()), 0)
  88  
  89          self.log.info("Mining blocks...")
  90  
  91          self.generate(self.nodes[0], 1, sync_fun=self.no_op)
  92  
  93          walletinfo = self.nodes[0].getwalletinfo()
  94          assert_equal(walletinfo['immature_balance'], 50)
  95          assert_equal(walletinfo['balance'], 0)
  96  
  97          self.sync_all(self.nodes[0:3])
  98          self.generate(self.nodes[1], COINBASE_MATURITY + 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
  99  
 100          assert_equal(self.nodes[0].getbalance(), 50)
 101          assert_equal(self.nodes[1].getbalance(), 50)
 102          assert_equal(self.nodes[2].getbalance(), 0)
 103  
 104          # Check that only first and second nodes have UTXOs
 105          utxos = self.nodes[0].listunspent()
 106          assert_equal(len(utxos), 1)
 107          assert_equal(len(self.nodes[1].listunspent()), 1)
 108          assert_equal(len(self.nodes[2].listunspent()), 0)
 109  
 110          self.log.info("Test gettxout")
 111          confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"]
 112          # First, outputs that are unspent both in the chain and in the
 113          # mempool should appear with or without include_mempool
 114          txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=False)
 115          assert_equal(txout['value'], 50)
 116          txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True)
 117          assert_equal(txout['value'], 50)
 118  
 119          # Send 21 BTC from 0 to 2 using sendtoaddress call.
 120          self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
 121          mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
 122  
 123          self.log.info("Test gettxout (second part)")
 124          # utxo spent in mempool should be visible if you exclude mempool
 125          # but invisible if you include mempool
 126          txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False)
 127          assert_equal(txout['value'], 50)
 128          txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index)  # by default include_mempool=True
 129          assert txout is None
 130          txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True)
 131          assert txout is None
 132          # new utxo from mempool should be invisible if you exclude mempool
 133          # but visible if you include mempool
 134          txout = self.nodes[0].gettxout(mempool_txid, 0, False)
 135          assert txout is None
 136          txout1 = self.nodes[0].gettxout(mempool_txid, 0, True)
 137          txout2 = self.nodes[0].gettxout(mempool_txid, 1, True)
 138          # note the mempool tx will have randomly assigned indices
 139          # but 10 will go to node2 and the rest will go to node0
 140          balance = self.nodes[0].getbalance()
 141          assert_equal(set([txout1['value'], txout2['value']]), set([10, balance]))
 142          walletinfo = self.nodes[0].getwalletinfo()
 143          assert_equal(walletinfo['immature_balance'], 0)
 144  
 145          # Have node0 mine a block, thus it will collect its own fee.
 146          self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 147  
 148          # Exercise locking of unspent outputs
 149          unspent_0 = self.nodes[2].listunspent()[0]
 150          unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
 151          # Trying to unlock an output which isn't locked should error
 152          assert_raises_rpc_error(-8, "Invalid parameter, expected locked output", self.nodes[2].lockunspent, True, [unspent_0])
 153  
 154          # Locking an already-locked output should error
 155          self.nodes[2].lockunspent(False, [unspent_0])
 156          assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
 157  
 158          # Restarting the node should clear the lock
 159          self.restart_node(2)
 160          self.nodes[2].lockunspent(False, [unspent_0])
 161  
 162          # Unloading and reloating the wallet should clear the lock
 163          assert_equal(self.nodes[0].listwallets(), [self.default_wallet_name])
 164          self.nodes[2].unloadwallet(self.default_wallet_name)
 165          self.nodes[2].loadwallet(self.default_wallet_name)
 166          assert_equal(len(self.nodes[2].listlockunspent()), 0)
 167  
 168          # Locking non-persistently, then re-locking persistently, is allowed
 169          self.nodes[2].lockunspent(False, [unspent_0])
 170          self.nodes[2].lockunspent(False, [unspent_0], True)
 171  
 172          # Restarting the node with the lock written to the wallet should keep the lock
 173          self.restart_node(2, ["-walletrejectlongchains=0"])
 174          assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
 175  
 176          # Unloading and reloading the wallet with a persistent lock should keep the lock
 177          self.nodes[2].unloadwallet(self.default_wallet_name)
 178          self.nodes[2].loadwallet(self.default_wallet_name)
 179          assert_raises_rpc_error(-8, "Invalid parameter, output already locked", self.nodes[2].lockunspent, False, [unspent_0])
 180  
 181          # Locked outputs should not be used, even if they are the only available funds
 182          assert_raises_rpc_error(-6, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
 183          assert_equal([unspent_0], self.nodes[2].listlockunspent())
 184  
 185          # Unlocking should remove the persistent lock
 186          self.nodes[2].lockunspent(True, [unspent_0])
 187          self.restart_node(2)
 188          assert_equal(len(self.nodes[2].listlockunspent()), 0)
 189  
 190          # Reconnect node 2 after restarts
 191          self.connect_nodes(1, 2)
 192          self.connect_nodes(0, 2)
 193  
 194          assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
 195                                  self.nodes[2].lockunspent, False,
 196                                  [{"txid": "0000000000000000000000000000000000", "vout": 0}])
 197          assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
 198                                  self.nodes[2].lockunspent, False,
 199                                  [{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
 200          assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
 201                                  self.nodes[2].lockunspent, False,
 202                                  [{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
 203          assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
 204                                  self.nodes[2].lockunspent, False,
 205                                  [{"txid": unspent_0["txid"], "vout": 999}])
 206  
 207          # The lock on a manually selected output is ignored
 208          unspent_0 = self.nodes[1].listunspent()[0]
 209          self.nodes[1].lockunspent(False, [unspent_0])
 210          tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
 211          self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})
 212  
 213          # fundrawtransaction can lock an input
 214          self.nodes[1].lockunspent(True, [unspent_0])
 215          assert_equal(len(self.nodes[1].listlockunspent()), 0)
 216          tx = self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})['hex']
 217          assert_equal(len(self.nodes[1].listlockunspent()), 1)
 218  
 219          # Send transaction
 220          tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
 221          self.nodes[1].sendrawtransaction(tx)
 222          assert_equal(len(self.nodes[1].listlockunspent()), 0)
 223  
 224          # Have node1 generate 100 blocks (so node0 can recover the fee)
 225          self.generate(self.nodes[1], COINBASE_MATURITY, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 226  
 227          # node0 should end up with 100 btc in block rewards plus fees, but
 228          # minus the 21 plus fees sent to node2
 229          assert_equal(self.nodes[0].getbalance(), 100 - 21)
 230          assert_equal(self.nodes[2].getbalance(), 21)
 231  
 232          # Node0 should have two unspent outputs.
 233          # Create a couple of transactions to send them to node2, submit them through
 234          # node1, and make sure both node0 and node2 pick them up properly:
 235          node0utxos = self.nodes[0].listunspent(1)
 236          assert_equal(len(node0utxos), 2)
 237  
 238          # create both transactions
 239          txns_to_send = []
 240          for utxo in node0utxos:
 241              inputs = []
 242              outputs = {}
 243              inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
 244              outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3
 245              raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
 246              txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))
 247  
 248          # Have node 1 (miner) send the transactions
 249          self.nodes[1].sendrawtransaction(hexstring=txns_to_send[0]["hex"], maxfeerate=0)
 250          self.nodes[1].sendrawtransaction(hexstring=txns_to_send[1]["hex"], maxfeerate=0)
 251  
 252          # Have node1 mine a block to confirm transactions:
 253          self.generate(self.nodes[1], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 254  
 255          assert_equal(self.nodes[0].getbalance(), 0)
 256          assert_equal(self.nodes[2].getbalance(), 94)
 257  
 258          # Verify that a spent output cannot be locked anymore
 259          spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
 260          assert_raises_rpc_error(-8, "Invalid parameter, expected unspent output", self.nodes[0].lockunspent, False, [spent_0])
 261  
 262          # Send 10 BTC normal
 263          address = self.nodes[0].getnewaddress("test")
 264          fee_per_byte = Decimal('0.001') / 1000
 265          self.nodes[2].settxfee(fee_per_byte * 1000)
 266          txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
 267          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 268          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']))
 269          assert_equal(self.nodes[0].getbalance(), Decimal('10'))
 270  
 271          # Send 10 BTC with subtract fee from amount
 272          txid = self.nodes[2].sendtoaddress(address, 10, "", "", True)
 273          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 274          node_2_bal -= Decimal('10')
 275          assert_equal(self.nodes[2].getbalance(), node_2_bal)
 276          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']))
 277  
 278          self.log.info("Test sendmany")
 279  
 280          # Sendmany 10 BTC
 281          txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
 282          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 283          node_0_bal += Decimal('10')
 284          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']))
 285          assert_equal(self.nodes[0].getbalance(), node_0_bal)
 286  
 287          # Sendmany 10 BTC with subtract fee from amount
 288          txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
 289          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 290          node_2_bal -= Decimal('10')
 291          assert_equal(self.nodes[2].getbalance(), node_2_bal)
 292          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']))
 293  
 294          # Sendmany 5 BTC to two addresses with subtracting fee from both addresses
 295          a0 = self.nodes[0].getnewaddress()
 296          a1 = self.nodes[0].getnewaddress()
 297          txid = self.nodes[2].sendmany(dummy='', amounts={a0: 5, a1: 5}, subtractfeefrom=[a0, a1])
 298          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 299          node_2_bal -= Decimal('10')
 300          assert_equal(self.nodes[2].getbalance(), node_2_bal)
 301          tx = self.nodes[2].gettransaction(txid)
 302          node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(tx['hex']))
 303          assert_equal(self.nodes[0].getbalance(), node_0_bal)
 304          expected_bal = Decimal('5') + (tx['fee'] / 2)
 305          assert_equal(self.nodes[0].getreceivedbyaddress(a0), expected_bal)
 306          assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal)
 307  
 308          self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)")
 309          fee_rate_sat_vb = 2
 310          fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
 311          explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000
 312  
 313          # Test passing fee_rate as a string
 314          txid = self.nodes[2].sendmany(amounts={address: 10}, fee_rate=str(fee_rate_sat_vb))
 315          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 316          balance = self.nodes[2].getbalance()
 317          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']))
 318          assert_equal(balance, node_2_bal)
 319          node_0_bal += Decimal('10')
 320          assert_equal(self.nodes[0].getbalance(), node_0_bal)
 321  
 322          # Test passing fee_rate as an integer
 323          amount = Decimal("0.0001")
 324          txid = self.nodes[2].sendmany(amounts={address: amount}, fee_rate=fee_rate_sat_vb)
 325          self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 326          balance = self.nodes[2].getbalance()
 327          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']))
 328          assert_equal(balance, node_2_bal)
 329          node_0_bal += amount
 330          assert_equal(self.nodes[0].getbalance(), node_0_bal)
 331  
 332          assert_raises_rpc_error(-8, "Unknown named parameter feeRate", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, feeRate=1)
 333  
 334          # Test setting explicit fee rate just below the minimum.
 335          self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
 336          assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
 337              self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.999)
 338  
 339          self.log.info("Test sendmany raises if an invalid fee_rate is passed")
 340          # Test fee_rate with zero values.
 341          msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"
 342          for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]:
 343              assert_raises_rpc_error(-6, msg, self.nodes[2].sendmany, amounts={address: 1}, fee_rate=zero_value)
 344          msg = "Invalid amount"
 345          # Test fee_rate values that don't pass fixed-point parsing checks.
 346          for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
 347              assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 1.0}, fee_rate=invalid_value)
 348          # Test fee_rate values that cannot be represented in sat/vB.
 349          for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
 350              assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=invalid_value)
 351          # Test fee_rate out of range (negative number).
 352          assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
 353          # Test type error.
 354          for invalid_value in [True, {"foo": "bar"}]:
 355              assert_raises_rpc_error(-3, NOT_A_NUMBER_OR_STRING, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=invalid_value)
 356  
 357          self.log.info("Test sendmany raises if an invalid conf_target or estimate_mode is passed")
 358          for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
 359              assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008",  # max value of 1008 per src/policy/fees.h
 360                  self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
 361          for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
 362              assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
 363                  self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
 364  
 365          self.start_node(3, self.nodes[3].extra_args)
 366          self.connect_nodes(0, 3)
 367          self.sync_all()
 368  
 369          # check if we can list zero value tx as available coins
 370          # 1. create raw_tx
 371          # 2. hex-changed one output to 0.0
 372          # 3. sign and send
 373          # 4. check if recipient (node0) can list the zero value tx
 374          usp = self.nodes[1].listunspent(query_options={'minimumAmount': '49.998'})[0]
 375          inputs = [{"txid": usp['txid'], "vout": usp['vout']}]
 376          outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}
 377  
 378          raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000")  # replace 11.11 with 0.0 (int32)
 379          signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx)
 380          decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
 381          zero_value_txid = decoded_raw_tx['txid']
 382          self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])
 383  
 384          self.sync_all()
 385          self.generate(self.nodes[1], 1)  # mine a block
 386  
 387          unspent_txs = self.nodes[0].listunspent()  # zero value tx must be in listunspents output
 388          found = False
 389          for uTx in unspent_txs:
 390              if uTx['txid'] == zero_value_txid:
 391                  found = True
 392                  assert_equal(uTx['amount'], Decimal('0'))
 393          assert found
 394  
 395          self.log.info("Test -walletbroadcast")
 396          self.stop_nodes()
 397          self.start_node(0, ["-walletbroadcast=0"])
 398          self.start_node(1, ["-walletbroadcast=0"])
 399          self.start_node(2, ["-walletbroadcast=0"])
 400          self.connect_nodes(0, 1)
 401          self.connect_nodes(1, 2)
 402          self.connect_nodes(0, 2)
 403          self.sync_all(self.nodes[0:3])
 404  
 405          txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
 406          tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
 407          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
 408          assert_equal(self.nodes[2].getbalance(), node_2_bal)  # should not be changed because tx was not broadcasted
 409  
 410          # now broadcast from another node, mine a block, sync, and check the balance
 411          self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
 412          self.generate(self.nodes[1], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 413          node_2_bal += 2
 414          tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
 415          assert_equal(self.nodes[2].getbalance(), node_2_bal)
 416  
 417          # create another tx
 418          self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
 419  
 420          # restart the nodes with -walletbroadcast=1
 421          self.stop_nodes()
 422          self.start_node(0)
 423          self.start_node(1)
 424          self.start_node(2)
 425          self.connect_nodes(0, 1)
 426          self.connect_nodes(1, 2)
 427          self.connect_nodes(0, 2)
 428          self.sync_blocks(self.nodes[0:3])
 429  
 430          self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_blocks(self.nodes[0:3]))
 431          node_2_bal += 2
 432  
 433          # tx should be added to balance because after restarting the nodes tx should be broadcast
 434          assert_equal(self.nodes[2].getbalance(), node_2_bal)
 435  
 436          # send a tx with value in a string (PR#6380 +)
 437          txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
 438          tx_obj = self.nodes[0].gettransaction(txid)
 439          assert_equal(tx_obj['amount'], Decimal('-2'))
 440  
 441          txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
 442          tx_obj = self.nodes[0].gettransaction(txid)
 443          assert_equal(tx_obj['amount'], Decimal('-0.0001'))
 444  
 445          # check if JSON parser can handle scientific notation in strings
 446          txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
 447          tx_obj = self.nodes[0].gettransaction(txid)
 448          assert_equal(tx_obj['amount'], Decimal('-0.0001'))
 449  
 450          # General checks for errors from incorrect inputs
 451          # This will raise an exception because the amount is negative
 452          assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1")
 453  
 454          # This will raise an exception because the amount type is wrong
 455          assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
 456  
 457          # This will raise an exception since generate does not accept a string
 458          assert_raises_rpc_error(-3, "not of expected type number", self.generate, self.nodes[0], "2")
 459  
 460          if not self.options.descriptors:
 461  
 462              # This will raise an exception for the invalid private key format
 463              assert_raises_rpc_error(-5, "Invalid private key encoding", self.nodes[0].importprivkey, "invalid")
 464  
 465              # This will raise an exception for importing an address with the PS2H flag
 466              temp_address = self.nodes[1].getnewaddress("", "p2sh-segwit")
 467              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)
 468  
 469              # This will raise an exception for attempting to dump the private key of an address you do not own
 470              assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address)
 471  
 472              # This will raise an exception for attempting to get the private key of an invalid Limenka address
 473              assert_raises_rpc_error(-5, "Invalid Limenka address", self.nodes[0].dumpprivkey, "invalid")
 474  
 475              # This will raise an exception for attempting to set a label for an invalid Limenka address
 476              assert_raises_rpc_error(-5, "Invalid Limenka address", self.nodes[0].setlabel, "invalid address", "label")
 477  
 478              # This will raise an exception for importing an invalid address
 479              assert_raises_rpc_error(-5, "Invalid Limenka address or script", self.nodes[0].importaddress, "invalid")
 480  
 481              # This will raise an exception for attempting to import a pubkey that isn't in hex
 482              assert_raises_rpc_error(-5, 'Pubkey "not hex" must be a hex string', self.nodes[0].importpubkey, "not hex")
 483  
 484              # This will raise exceptions for importing a pubkeys with invalid length / invalid coordinates
 485              too_short_pubkey = "5361746f736869204e616b616d6f746f"
 486              assert_raises_rpc_error(-5, f'Pubkey "{too_short_pubkey}" must have a length of either 33 or 65 bytes', self.nodes[0].importpubkey, too_short_pubkey)
 487              not_on_curve_pubkey = bytes([4] + [0]*64).hex()  # pubkey with coordinates (0,0) is not on curve
 488              assert_raises_rpc_error(-5, f'Pubkey "{not_on_curve_pubkey}" must be cryptographically valid', self.nodes[0].importpubkey, not_on_curve_pubkey)
 489  
 490              # Bech32m addresses cannot be imported into a legacy wallet
 491              assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6")
 492  
 493              # Import address and private key to check correct behavior of spendable unspents
 494              # 1. Send some coins to generate new UTXO
 495              address_to_import = self.nodes[2].getnewaddress()
 496              utxo = self.create_outpoints(self.nodes[0], outputs=[{address_to_import: 1}])[0]
 497              self.sync_mempools(self.nodes[0:3])
 498              self.nodes[2].lockunspent(False, [utxo])
 499              self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 500  
 501              self.log.info("Test sendtoaddress with fee_rate param (explicit fee rate in sat/vB)")
 502              prebalance = self.nodes[2].getbalance()
 503              assert prebalance > 2
 504              address = self.nodes[1].getnewaddress()
 505              amount = 3
 506              fee_rate_sat_vb = 2
 507              fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
 508              # Test passing fee_rate as an integer
 509              txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb)
 510              tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
 511              self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 512              postbalance = self.nodes[2].getbalance()
 513              fee = prebalance - postbalance - Decimal(amount)
 514              assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
 515  
 516              prebalance = self.nodes[2].getbalance()
 517              amount = Decimal("0.001")
 518              fee_rate_sat_vb = 1.23
 519              fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
 520              # Test passing fee_rate as a string
 521              txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=str(fee_rate_sat_vb))
 522              tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
 523              self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 524              postbalance = self.nodes[2].getbalance()
 525              fee = prebalance - postbalance - amount
 526              assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
 527  
 528              # Test setting explicit fee rate just below the minimum.
 529              self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
 530              assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
 531                  self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.999)
 532  
 533              self.log.info("Test sendtoaddress raises if an invalid fee_rate is passed")
 534              # Test fee_rate with zero values.
 535              msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"
 536              for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]:
 537                  assert_raises_rpc_error(-6, msg, self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=zero_value)
 538              msg = "Invalid amount"
 539              # Test fee_rate values that don't pass fixed-point parsing checks.
 540              for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
 541                  assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=invalid_value)
 542              # Test fee_rate values that cannot be represented in sat/vB.
 543              for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
 544                  assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=invalid_value)
 545              # Test fee_rate out of range (negative number).
 546              assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)
 547              # Test type error.
 548              for invalid_value in [True, {"foo": "bar"}]:
 549                  assert_raises_rpc_error(-3, NOT_A_NUMBER_OR_STRING, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=invalid_value)
 550  
 551              self.log.info("Test sendtoaddress raises if an invalid conf_target or estimate_mode is passed")
 552              for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
 553                  assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008",  # max value of 1008 per src/policy/fees.h
 554                      self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
 555              for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
 556                  assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
 557                      self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
 558  
 559              # 2. Import address from node2 to node1
 560              self.nodes[1].importaddress(address_to_import)
 561  
 562              # 3. Validate that the imported address is watch-only on node1
 563              assert self.nodes[1].getaddressinfo(address_to_import)["iswatchonly"]
 564  
 565              # 4. Check that the unspents after import are not spendable
 566              assert_array_result(self.nodes[1].listunspent(),
 567                                  {"address": address_to_import},
 568                                  {"spendable": False})
 569  
 570              # 5. Import private key of the previously imported address on node1
 571              priv_key = self.nodes[2].dumpprivkey(address_to_import)
 572              self.nodes[1].importprivkey(priv_key)
 573  
 574              # 6. Check that the unspents are now spendable on node1
 575              assert_array_result(self.nodes[1].listunspent(),
 576                                  {"address": address_to_import},
 577                                  {"spendable": True})
 578  
 579          # Test importaddress on a blank, private keys disabled, legacy wallet with no descriptors support
 580          self.test_legacy_importaddress()
 581  
 582          # Mine a block from node0 to an address from node1
 583          coinbase_addr = self.nodes[1].getnewaddress()
 584          block_hash = self.generatetoaddress(self.nodes[0], 1, coinbase_addr, sync_fun=lambda: self.sync_all(self.nodes[0:3]))[0]
 585          coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
 586  
 587          # Check that the txid and balance is found by node1
 588          self.nodes[1].gettransaction(coinbase_txid)
 589  
 590          # check if wallet or blockchain maintenance changes the balance
 591          self.sync_all(self.nodes[0:3])
 592          blocks = self.generate(self.nodes[0], 2, sync_fun=lambda: self.sync_all(self.nodes[0:3]))
 593          balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
 594          block_count = self.nodes[0].getblockcount()
 595  
 596          # Check modes:
 597          #   - True: unicode escaped as \u....
 598          #   - False: unicode directly as UTF-8
 599          for mode in [True, False]:
 600              self.nodes[0].rpc.ensure_ascii = mode
 601              # unicode check: Basic Multilingual Plane, Supplementary Plane respectively
 602              for label in [u'рыба', u'𝅘𝅥𝅯']:
 603                  addr = self.nodes[0].getnewaddress()
 604                  self.nodes[0].setlabel(addr, label)
 605                  test_address(self.nodes[0], addr, labels=[label])
 606                  assert label in self.nodes[0].listlabels()
 607          self.nodes[0].rpc.ensure_ascii = True  # restore to default
 608  
 609          # -reindex tests
 610          chainlimit = 6
 611          self.log.info("Test -reindex")
 612          self.stop_nodes()
 613          # set lower ancestor limit for later
 614          self.start_node(0, ['-reindex', "-walletrejectlongchains=0", "-limitancestorcount=" + str(chainlimit)])
 615          self.start_node(1, ['-reindex', "-limitancestorcount=" + str(chainlimit)])
 616          self.start_node(2, ['-reindex', "-limitancestorcount=" + str(chainlimit)])
 617          # reindex will leave rpc warm up "early"; Wait for it to finish
 618          self.wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
 619          assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])
 620  
 621          # Exercise listsinceblock with the last two blocks
 622          coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0])
 623          assert_equal(coinbase_tx_1["lastblock"], blocks[1])
 624          assert_equal(len(coinbase_tx_1["transactions"]), 1)
 625          assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1])
 626          assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0)
 627  
 628          # ==Check that wallet prefers to use coins that don't exceed mempool limits =====
 629  
 630          # Get all non-zero utxos together and split into two chains
 631          chain_addrs = [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()]
 632          self.nodes[0].sendall(recipients=chain_addrs)
 633          self.generate(self.nodes[0], 1, sync_fun=self.no_op)
 634  
 635          # Make a long chain of unconfirmed payments without hitting mempool limit
 636          # Each tx we make leaves only one output of change on a chain 1 longer
 637          # Since the amount to send is always much less than the outputs, we only ever need one output
 638          # So we should be able to generate exactly chainlimit txs for each original output
 639          sending_addr = self.nodes[1].getnewaddress()
 640          txid_list = []
 641          for _ in range(chainlimit * 2):
 642              txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
 643          assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
 644          assert_equal(len(txid_list), chainlimit * 2)
 645  
 646          # Without walletrejectlongchains, we will still generate a txid
 647          # The tx will be stored in the wallet but not accepted to the mempool
 648          extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001'))
 649          assert extra_txid not in self.nodes[0].getrawmempool()
 650          assert extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()]
 651          self.nodes[0].abandontransaction(extra_txid)
 652          total_txs = len(self.nodes[0].listtransactions("*", 99999))
 653  
 654          # Try with walletrejectlongchains
 655          # Double chain limit but require combining inputs, so we pass AttemptSelection
 656          self.stop_node(0)
 657          extra_args = ["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)]
 658          self.start_node(0, extra_args=extra_args)
 659  
 660          # wait until the wallet has submitted all transactions to the mempool
 661          self.wait_until(lambda: len(self.nodes[0].getrawmempool()) == chainlimit * 2)
 662  
 663          # Prevent potential race condition when calling wallet RPCs right after restart
 664          self.nodes[0].syncwithvalidationinterfacequeue()
 665  
 666          node0_balance = self.nodes[0].getbalance()
 667          # With walletrejectlongchains we will not create the tx and store it in our wallet.
 668          assert_raises_rpc_error(-6, f"too many unconfirmed ancestors [limit: {chainlimit * 2}]", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
 669  
 670          # Verify nothing new in wallet
 671          assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
 672  
 673          # Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py
 674          assert_raises_rpc_error(-5, "Invalid or unsupported Base58-encoded address.", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
 675          address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
 676          assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
 677          assert_equal(address_info["scriptPubKey"], "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac")
 678          assert not address_info["ismine"]
 679          assert not address_info["iswatchonly"]
 680          assert not address_info["isscript"]
 681          assert not address_info["ischange"]
 682          assert_equal(address_info['use_txids'], [])
 683  
 684          # Test getaddressinfo 'use_txids' field
 685          addr = "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ"
 686          txid_1 = self.nodes[0].sendtoaddress(addr, 1)
 687          address_info = self.nodes[0].getaddressinfo(addr)
 688          assert_equal(address_info['use_txids'], [txid_1])
 689          txid_2 = self.nodes[0].sendtoaddress(addr, 1)
 690          address_info = self.nodes[0].getaddressinfo(addr)
 691          assert_equal(sorted(address_info['use_txids']), sorted([txid_1, txid_2]))
 692  
 693          # Test getaddressinfo 'ischange' field on change address.
 694          self.generate(self.nodes[0], 1, sync_fun=self.no_op)
 695          destination = self.nodes[1].getnewaddress()
 696          txid = self.nodes[0].sendtoaddress(destination, 0.123)
 697          tx = self.nodes[0].gettransaction(txid=txid, verbose=True)['decoded']
 698          output_addresses = [vout['scriptPubKey']['address'] for vout in tx["vout"]]
 699          assert len(output_addresses) > 1
 700          for address in output_addresses:
 701              ischange = self.nodes[0].getaddressinfo(address)['ischange']
 702              assert_equal(ischange, address != destination)
 703              if ischange:
 704                  change = address
 705          self.nodes[0].setlabel(change, 'foobar')
 706          assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)
 707  
 708          # Test gettransaction response with different arguments.
 709          self.log.info("Testing gettransaction response with different arguments...")
 710          self.nodes[0].setlabel(change, 'baz')
 711          baz = self.nodes[0].listtransactions(label="baz", count=1)[0]
 712          expected_receive_vout = {"label":    "baz",
 713                                   "address":  baz["address"],
 714                                   "amount":   baz["amount"],
 715                                   "category": baz["category"],
 716                                   "vout":     baz["vout"]}
 717          expected_fields = frozenset({
 718              'amount',
 719              'bip125-replaceable',
 720              'confirmations',
 721              'details',
 722              'fee',
 723              'hex',
 724              'in_mempool',
 725              'lastprocessedblock',
 726              'mempoolconflicts',
 727              'time',
 728              'timereceived',
 729              'trusted',
 730              'txid',
 731              'wtxid',
 732              'walletconflicts',
 733          })
 734          verbose_field = "decoded"
 735          expected_verbose_fields = expected_fields | {verbose_field}
 736  
 737          self.log.debug("Testing gettransaction response without verbose")
 738          tx = self.nodes[0].gettransaction(txid=txid)
 739          assert_equal(set([*tx]), expected_fields)
 740          assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)
 741  
 742          self.log.debug("Testing gettransaction response with verbose set to False")
 743          tx = self.nodes[0].gettransaction(txid=txid, verbose=False)
 744          assert_equal(set([*tx]), expected_fields)
 745          assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)
 746  
 747          self.log.debug("Testing gettransaction response with verbose set to True")
 748          tx = self.nodes[0].gettransaction(txid=txid, verbose=True)
 749          assert_equal(set([*tx]), expected_verbose_fields)
 750          assert_array_result(tx["details"], {"category": "receive"}, expected_receive_vout)
 751          assert_equal(tx[verbose_field], self.nodes[0].decoderawtransaction(tx["hex"]))
 752  
 753          self.log.info("Test send* RPCs with verbose=True")
 754          address = self.nodes[0].getnewaddress("test")
 755          txid_feeReason_one = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=True)
 756          assert_equal(txid_feeReason_one["fee_reason"], "Fallback fee")
 757          txid_feeReason_two = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=True)
 758          assert_equal(txid_feeReason_two["fee_reason"], "Fallback fee")
 759          self.log.info("Test send* RPCs with verbose=False")
 760          txid_feeReason_three = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=False)
 761          assert_equal(self.nodes[2].gettransaction(txid_feeReason_three)['txid'], txid_feeReason_three)
 762          txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
 763          assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
 764  
 765          if self.options.descriptors:
 766              self.log.info("Testing 'listunspent' outputs the parent descriptor(s) of coins")
 767              # Create two multisig descriptors, and send a UTxO each.
 768              multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))")
 769              multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))")
 770              addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0]
 771              addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0]
 772              txid_a = self.nodes[0].sendtoaddress(addr_a, 0.01)
 773              txid_b = self.nodes[0].sendtoaddress(addr_b, 0.01)
 774              self.generate(self.nodes[0], 1, sync_fun=self.no_op)
 775              # Prevent race of listunspent with outstanding TxAddedToMempool notifications
 776              self.nodes[0].syncwithvalidationinterfacequeue()
 777              # Now import the descriptors, make sure we can identify on which descriptor each coin was received.
 778              self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True)
 779              wo_wallet = self.nodes[0].get_wallet_rpc("wo")
 780              wo_wallet.importdescriptors([
 781                  {
 782                      "desc": multi_a,
 783                      "active": False,
 784                      "timestamp": "now",
 785                  },
 786                  {
 787                      "desc": multi_b,
 788                      "active": False,
 789                      "timestamp": "now",
 790                  },
 791              ])
 792              coins = wo_wallet.listunspent(minconf=0)
 793              assert_equal(len(coins), 2)
 794              coin_a = next(c for c in coins if c["txid"] == txid_a)
 795              assert_equal(coin_a["parent_descs"][0], multi_a)
 796              coin_b = next(c for c in coins if c["txid"] == txid_b)
 797              assert_equal(coin_b["parent_descs"][0], multi_b)
 798              self.nodes[0].unloadwallet("wo")
 799  
 800          self.log.info("Test -spendzeroconfchange")
 801          self.restart_node(0, ["-spendzeroconfchange=0"])
 802  
 803          # create new wallet and fund it with a confirmed UTXO
 804          self.nodes[0].createwallet(wallet_name="zeroconf", load_on_startup=True)
 805          zeroconf_wallet = self.nodes[0].get_wallet_rpc("zeroconf")
 806          default_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
 807          default_wallet.sendtoaddress(zeroconf_wallet.getnewaddress(), Decimal('1.0'))
 808          self.generate(self.nodes[0], 1, sync_fun=self.no_op)
 809          utxos = zeroconf_wallet.listunspent(minconf=0)
 810          assert_equal(len(utxos), 1)
 811          assert_equal(utxos[0]['confirmations'], 1)
 812  
 813          # spend confirmed UTXO to ourselves
 814          zeroconf_wallet.sendall(recipients=[zeroconf_wallet.getnewaddress()])
 815          utxos = zeroconf_wallet.listunspent(minconf=0)
 816          assert_equal(len(utxos), 1)
 817          assert_equal(utxos[0]['confirmations'], 0)
 818          # accounts for untrusted pending balance
 819          bal = zeroconf_wallet.getbalances()
 820          assert_equal(bal['mine']['trusted'], 0)
 821          assert_equal(bal['mine']['untrusted_pending'], utxos[0]['amount'])
 822  
 823          # spending an unconfirmed UTXO sent to ourselves should fail
 824          assert_raises_rpc_error(-6, "Insufficient funds", zeroconf_wallet.sendtoaddress, zeroconf_wallet.getnewaddress(), Decimal('0.5'))
 825  
 826          # check that it works again with -spendzeroconfchange set (=default)
 827          self.restart_node(0, ["-spendzeroconfchange=1"])
 828          # Make sure the wallet knows the tx in the mempool
 829          self.nodes[0].syncwithvalidationinterfacequeue()
 830  
 831          zeroconf_wallet = self.nodes[0].get_wallet_rpc("zeroconf")
 832          utxos = zeroconf_wallet.listunspent(minconf=0)
 833          assert_equal(len(utxos), 1)
 834          assert_equal(utxos[0]['confirmations'], 0)
 835          # accounts for trusted balance
 836          bal = zeroconf_wallet.getbalances()
 837          assert_equal(bal['mine']['trusted'], utxos[0]['amount'])
 838          assert_equal(bal['mine']['untrusted_pending'], 0)
 839  
 840          zeroconf_wallet.sendtoaddress(zeroconf_wallet.getnewaddress(), Decimal('0.5'))
 841  
 842          self.test_chain_listunspent()
 843  
 844      def test_chain_listunspent(self):
 845          if not self.options.descriptors:
 846              return
 847          self.wallet = MiniWallet(self.nodes[0])
 848          self.nodes[0].get_wallet_rpc(self.default_wallet_name).sendtoaddress(self.wallet.get_address(), "5")
 849          self.generate(self.wallet, 1, sync_fun=self.no_op)
 850          self.nodes[0].createwallet("watch_wallet", disable_private_keys=True)
 851          watch_wallet = self.nodes[0].get_wallet_rpc("watch_wallet")
 852          watch_wallet.importaddress(self.wallet.get_address())
 853  
 854          # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine
 855          chain = self.wallet.create_self_transfer_chain(chain_length=DEFAULT_ANCESTOR_LIMIT)
 856          ancestor_vsize = 0
 857          ancestor_fees = Decimal(0)
 858  
 859          for i, t in enumerate(chain):
 860              ancestor_vsize += t["tx"].get_vsize()
 861              ancestor_fees += t["fee"]
 862              self.wallet.sendrawtransaction(from_node=self.nodes[0], tx_hex=t["hex"])
 863              # Check that listunspent ancestor{count, size, fees} yield the correct results
 864              wallet_unspent = watch_wallet.listunspent(minconf=0)
 865              this_unspent = next(utxo_info for utxo_info in wallet_unspent if utxo_info["txid"] == t["txid"])
 866              assert_equal(this_unspent['ancestorcount'], i + 1)
 867              assert_equal(this_unspent['ancestorsize'], ancestor_vsize)
 868              assert_equal(this_unspent['ancestorfees'], ancestor_fees * COIN)
 869  
 870  
 871  if __name__ == '__main__':
 872      WalletTest(__file__).main()
 873