wallet_spend_unconfirmed.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2022-present The Bitcoin Core developers
   3  # Distributed under the MIT software license, see the accompanying
   4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  
   6  from decimal import Decimal, getcontext
   7  
   8  from test_framework.test_framework import BitcoinTestFramework
   9  from test_framework.util import (
  10      assert_greater_than_or_equal,
  11      assert_equal,
  12      find_vout_for_address,
  13  )
  14  
  15  class UnconfirmedInputTest(BitcoinTestFramework):
  16      def set_test_params(self):
  17          getcontext().prec=9
  18          self.setup_clean_chain = True
  19          self.num_nodes = 1
  20  
  21      def setup_and_fund_wallet(self, walletname):
  22          self.nodes[0].createwallet(walletname)
  23          wallet = self.nodes[0].get_wallet_rpc(walletname)
  24  
  25          self.def_wallet.sendtoaddress(address=wallet.getnewaddress(), amount=2)
  26          self.generate(self.nodes[0], 1) # confirm funding tx
  27          return wallet
  28  
  29      def skip_test_if_missing_module(self):
  30          self.skip_if_no_wallet()
  31  
  32      def calc_fee_rate(self, tx):
  33          fee = Decimal(-1e8) * tx["fee"]
  34          vsize = tx["decoded"]["vsize"]
  35          return fee / vsize
  36  
  37      def calc_set_fee_rate(self, txs):
  38          fees = Decimal(-1e8) * sum([tx["fee"] for tx in txs]) # fee is negative!
  39          vsizes = sum([tx["decoded"]["vsize"] for tx in txs])
  40          return fees / vsizes
  41  
  42      def assert_spends_only_parents(self, tx, parent_txids):
  43          parent_checklist = parent_txids.copy()
  44          number_inputs = len(tx["decoded"]["vin"])
  45          assert_equal(number_inputs, len(parent_txids))
  46          for i in range(number_inputs):
  47              txid_of_input = tx["decoded"]["vin"][i]["txid"]
  48              assert txid_of_input in parent_checklist
  49              parent_checklist.remove(txid_of_input)
  50  
  51      def assert_undershoots_target(self, tx):
  52          resulting_fee_rate = self.calc_fee_rate(tx)
  53          assert_greater_than_or_equal(self.target_fee_rate, resulting_fee_rate)
  54  
  55      def assert_beats_target(self, tx):
  56          resulting_fee_rate = self.calc_fee_rate(tx)
  57          assert_greater_than_or_equal(resulting_fee_rate, self.target_fee_rate)
  58  
  59      # Meta-Test: try feerate testing function on confirmed UTXO
  60      def test_target_feerate_confirmed(self):
  61          self.log.info("Start test feerate with confirmed input")
  62          wallet = self.setup_and_fund_wallet("confirmed_wallet")
  63  
  64          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
  65          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
  66          self.assert_beats_target(ancestor_aware_tx)
  67  
  68          wallet.unloadwallet()
  69  
  70      # Spend unconfirmed UTXO from high-feerate parent
  71      def test_target_feerate_unconfirmed_high(self):
  72          self.log.info("Start test feerate with high feerate unconfirmed input")
  73          wallet = self.setup_and_fund_wallet("unconfirmed_high_wallet")
  74  
  75          # Send unconfirmed transaction with high feerate to testing wallet
  76          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=3*self.target_fee_rate)
  77          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
  78          self.assert_beats_target(parent_tx)
  79  
  80          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
  81          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
  82  
  83          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
  84  
  85          self.assert_beats_target(ancestor_aware_tx)
  86  
  87          wallet.unloadwallet()
  88  
  89      # Spend unconfirmed UTXO from low-feerate parent. Expect that parent gets
  90      # bumped to target feerate.
  91      def test_target_feerate_unconfirmed_low(self):
  92          self.log.info("Start test feerate with low feerate unconfirmed input")
  93          wallet = self.setup_and_fund_wallet("unconfirmed_low_wallet")
  94  
  95          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
  96          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
  97  
  98          self.assert_undershoots_target(parent_tx)
  99  
 100          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
 101          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 102  
 103          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 104  
 105          self.assert_beats_target(ancestor_aware_tx)
 106          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 107          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 108          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 109  
 110          wallet.unloadwallet()
 111  
 112      # Spend UTXO with unconfirmed low feerate parent and grandparent
 113      # txs. Expect that both ancestors get bumped to target feerate.
 114      def test_chain_of_unconfirmed_low(self):
 115          self.log.info("Start test with parent and grandparent tx")
 116          wallet = self.setup_and_fund_wallet("unconfirmed_low_chain_wallet")
 117  
 118          grandparent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.8, fee_rate=1)
 119          gp_tx = wallet.gettransaction(txid=grandparent_txid, verbose=True)
 120  
 121          self.assert_undershoots_target(gp_tx)
 122  
 123          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=2)
 124          p_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 125  
 126          self.assert_undershoots_target(p_tx)
 127  
 128          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=1.3, fee_rate=self.target_fee_rate)
 129          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 130          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 131  
 132          self.assert_beats_target(ancestor_aware_tx)
 133          resulting_ancestry_fee_rate = self.calc_set_fee_rate([gp_tx, p_tx, ancestor_aware_tx])
 134          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 135          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 136  
 137          wallet.unloadwallet()
 138  
 139      # Spend unconfirmed UTXOs from two low feerate parent txs.
 140      def test_two_low_feerate_unconfirmed_parents(self):
 141          self.log.info("Start test with two unconfirmed parent txs")
 142          wallet = self.setup_and_fund_wallet("two_parents_wallet")
 143  
 144          # Add second UTXO to tested wallet
 145          self.def_wallet.sendtoaddress(address=wallet.getnewaddress(), amount=2)
 146          self.generate(self.nodes[0], 1) # confirm funding tx
 147  
 148          parent_one_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=2)
 149          p_one_tx = wallet.gettransaction(txid=parent_one_txid, verbose=True)
 150          self.assert_undershoots_target(p_one_tx)
 151  
 152          parent_two_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=1)
 153          p_two_tx = wallet.gettransaction(txid=parent_two_txid, verbose=True)
 154          self.assert_undershoots_target(p_two_tx)
 155  
 156          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=2.8, fee_rate=self.target_fee_rate)
 157          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 158          self.assert_spends_only_parents(ancestor_aware_tx, [parent_one_txid, parent_two_txid])
 159  
 160          self.assert_beats_target(ancestor_aware_tx)
 161          resulting_ancestry_fee_rate = self.calc_set_fee_rate([p_one_tx, p_two_tx, ancestor_aware_tx])
 162          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 163          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 164  
 165          wallet.unloadwallet()
 166  
 167      # Spend two unconfirmed inputs, one each from low and high feerate parents
 168      def test_mixed_feerate_unconfirmed_parents(self):
 169          self.log.info("Start test with two unconfirmed parent txs one of which has a higher feerate")
 170          wallet = self.setup_and_fund_wallet("two_mixed_parents_wallet")
 171  
 172          # Add second UTXO to tested wallet
 173          self.def_wallet.sendtoaddress(address=wallet.getnewaddress(), amount=2)
 174          self.generate(self.nodes[0], 1) # confirm funding tx
 175  
 176          high_parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=self.target_fee_rate*2)
 177          p_high_tx = wallet.gettransaction(txid=high_parent_txid, verbose=True)
 178          # This time the parent is greater than the child
 179          self.assert_beats_target(p_high_tx)
 180  
 181          parent_low_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=1)
 182          p_low_tx = wallet.gettransaction(txid=parent_low_txid, verbose=True)
 183          # Other parent needs bump
 184          self.assert_undershoots_target(p_low_tx)
 185  
 186          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=2.8, fee_rate=self.target_fee_rate)
 187          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 188          self.assert_spends_only_parents(ancestor_aware_tx, [parent_low_txid, high_parent_txid])
 189  
 190          self.assert_beats_target(ancestor_aware_tx)
 191          resulting_ancestry_fee_rate = self.calc_set_fee_rate([p_high_tx, p_low_tx, ancestor_aware_tx])
 192          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 193  
 194          resulting_bumped_ancestry_fee_rate = self.calc_set_fee_rate([p_low_tx, ancestor_aware_tx])
 195          assert_greater_than_or_equal(resulting_bumped_ancestry_fee_rate, self.target_fee_rate)
 196          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_bumped_ancestry_fee_rate)
 197  
 198          wallet.unloadwallet()
 199  
 200      # Spend from chain with high feerate grandparent and low feerate parent
 201      def test_chain_of_high_low(self):
 202          self.log.info("Start test with low parent and high grandparent tx")
 203          wallet = self.setup_and_fund_wallet("high_low_chain_wallet")
 204  
 205          grandparent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.8, fee_rate=self.target_fee_rate * 10)
 206          gp_tx = wallet.gettransaction(txid=grandparent_txid, verbose=True)
 207          # grandparent has higher feerate
 208          self.assert_beats_target(gp_tx)
 209  
 210          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=1)
 211          # parent is low feerate
 212          p_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 213          self.assert_undershoots_target(p_tx)
 214  
 215          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=1.3, fee_rate=self.target_fee_rate)
 216          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 217          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 218  
 219          self.assert_beats_target(ancestor_aware_tx)
 220          resulting_ancestry_fee_rate = self.calc_set_fee_rate([p_tx, ancestor_aware_tx])
 221          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 222          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 223          resulting_ancestry_fee_rate_with_high_feerate_gp = self.calc_set_fee_rate([gp_tx, p_tx, ancestor_aware_tx])
 224          # Check that we bumped the parent without relying on the grandparent
 225          assert_greater_than_or_equal(resulting_ancestry_fee_rate_with_high_feerate_gp, self.target_fee_rate*1.1)
 226  
 227          wallet.unloadwallet()
 228  
 229      # Spend UTXO from chain of unconfirmed transactions with low feerate
 230      # grandparent and even lower feerate parent
 231      def test_chain_of_high_low_below_target_feerate(self):
 232          self.log.info("Start test with low parent and higher low grandparent tx")
 233          wallet = self.setup_and_fund_wallet("low_and_lower_chain_wallet")
 234  
 235          grandparent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.8, fee_rate=5)
 236          gp_tx = wallet.gettransaction(txid=grandparent_txid, verbose=True)
 237  
 238          # grandparent has higher feerate, but below target
 239          self.assert_undershoots_target(gp_tx)
 240  
 241          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1.5, fee_rate=1)
 242          p_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 243          # parent even lower
 244          self.assert_undershoots_target(p_tx)
 245  
 246          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=1.3, fee_rate=self.target_fee_rate)
 247          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 248          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 249  
 250          self.assert_beats_target(ancestor_aware_tx)
 251          resulting_ancestry_fee_rate = self.calc_set_fee_rate([gp_tx, p_tx, ancestor_aware_tx])
 252          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 253          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 254  
 255          wallet.unloadwallet()
 256  
 257      # Test fee calculation when bumping while using subtract fee from output (SFFO)
 258      def test_target_feerate_unconfirmed_low_sffo(self):
 259          self.log.info("Start test feerate with low feerate unconfirmed input, while subtracting from output")
 260          wallet = self.setup_and_fund_wallet("unconfirmed_low_wallet_sffo")
 261  
 262          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
 263          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 264  
 265          self.assert_undershoots_target(parent_tx)
 266  
 267          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate, subtractfeefromamount=True)
 268          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 269  
 270          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 271  
 272          self.assert_beats_target(ancestor_aware_tx)
 273          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 274          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 275          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 276  
 277          wallet.unloadwallet()
 278  
 279      # Test that parents of preset unconfirmed inputs get cpfp'ed
 280      def test_preset_input_cpfp(self):
 281          self.log.info("Start test with preset input from low feerate unconfirmed transaction")
 282          wallet = self.setup_and_fund_wallet("preset_input")
 283  
 284          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
 285          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 286  
 287          self.assert_undershoots_target(parent_tx)
 288  
 289          number_outputs = len(parent_tx["decoded"]["vout"])
 290          assert_equal(number_outputs, 2)
 291  
 292          # we don't care which of the two outputs we spent, they're both ours
 293          ancestor_aware_txid = wallet.send(outputs=[{self.def_wallet.getnewaddress(): 0.5}], fee_rate=self.target_fee_rate, options={"add_inputs": True, "inputs": [{"txid": parent_txid, "vout": 0}]})["txid"]
 294          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 295  
 296          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 297  
 298          self.assert_beats_target(ancestor_aware_tx)
 299          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 300          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 301          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 302  
 303          wallet.unloadwallet()
 304  
 305      # Test that RBFing a transaction with unconfirmed input gets the right feerate
 306      def test_rbf_bumping(self):
 307          self.log.info("Start test to rbf a transaction unconfirmed input to bump it")
 308          wallet = self.setup_and_fund_wallet("bump")
 309  
 310          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
 311          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 312  
 313          self.assert_undershoots_target(parent_tx)
 314  
 315          to_be_rbfed_ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
 316          ancestor_aware_tx = wallet.gettransaction(txid=to_be_rbfed_ancestor_aware_txid, verbose=True)
 317  
 318          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 319  
 320          self.assert_beats_target(ancestor_aware_tx)
 321          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 322          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 323          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 324  
 325          bumped_ancestor_aware_txid = wallet.bumpfee(txid=to_be_rbfed_ancestor_aware_txid, options={"fee_rate": self.target_fee_rate * 2} )["txid"]
 326          bumped_ancestor_aware_tx = wallet.gettransaction(txid=bumped_ancestor_aware_txid, verbose=True)
 327          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 328  
 329          resulting_bumped_fee_rate = self.calc_fee_rate(bumped_ancestor_aware_tx)
 330          assert_greater_than_or_equal(resulting_bumped_fee_rate, 2*self.target_fee_rate)
 331          resulting_bumped_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, bumped_ancestor_aware_tx])
 332          assert_greater_than_or_equal(resulting_bumped_ancestry_fee_rate, 2*self.target_fee_rate)
 333          assert_greater_than_or_equal(2*self.target_fee_rate*1.01, resulting_bumped_ancestry_fee_rate)
 334  
 335          wallet.unloadwallet()
 336  
 337      # Test that transaction spending two UTXOs with overlapping ancestry does not bump shared ancestors twice
 338      def test_target_feerate_unconfirmed_low_overlapping_ancestry(self):
 339          self.log.info("Start test where two UTXOs have overlapping ancestry")
 340          wallet = self.setup_and_fund_wallet("overlapping_ancestry_wallet")
 341  
 342          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
 343          two_output_parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 344  
 345          self.assert_undershoots_target(two_output_parent_tx)
 346  
 347          # spend both outputs from parent transaction
 348          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=1.5, fee_rate=self.target_fee_rate)
 349          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 350          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid, parent_txid])
 351  
 352          self.assert_beats_target(ancestor_aware_tx)
 353          resulting_ancestry_fee_rate = self.calc_set_fee_rate([two_output_parent_tx, ancestor_aware_tx])
 354          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 355          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 356  
 357          wallet.unloadwallet()
 358  
 359      # Test that new transaction ignores sibling transaction with low feerate
 360      def test_sibling_tx_gets_ignored(self):
 361          self.log.info("Start test where a low-fee sibling tx gets created and check that bumping ignores it")
 362          wallet = self.setup_and_fund_wallet("ignore-sibling")
 363  
 364          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=2)
 365          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 366  
 367          self.assert_undershoots_target(parent_tx)
 368  
 369          # create sibling tx
 370          sibling_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.9, fee_rate=1)
 371          sibling_tx = wallet.gettransaction(txid=sibling_txid, verbose=True)
 372          self.assert_undershoots_target(sibling_tx)
 373  
 374          # spend both outputs from parent transaction
 375          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
 376          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 377  
 378          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 379  
 380          self.assert_beats_target(ancestor_aware_tx)
 381          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 382          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 383          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 384  
 385          wallet.unloadwallet()
 386  
 387      # Test that new transaction only pays for itself when high feerate sibling pays for parent
 388      def test_sibling_tx_bumps_parent(self):
 389          self.log.info("Start test where a high-fee sibling tx bumps the parent")
 390          wallet = self.setup_and_fund_wallet("generous-sibling")
 391  
 392          parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=1)
 393          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 394          self.assert_undershoots_target(parent_tx)
 395  
 396          # create sibling tx
 397          sibling_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.9, fee_rate=3*self.target_fee_rate)
 398          sibling_tx = wallet.gettransaction(txid=sibling_txid, verbose=True)
 399          self.assert_beats_target(sibling_tx)
 400  
 401          # spend both outputs from parent transaction
 402          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=0.5, fee_rate=self.target_fee_rate)
 403          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 404  
 405          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 406  
 407          self.assert_beats_target(ancestor_aware_tx)
 408          # Child is only paying for itself…
 409          resulting_fee_rate = self.calc_fee_rate(ancestor_aware_tx)
 410          assert_greater_than_or_equal(1.05 * self.target_fee_rate, resulting_fee_rate)
 411          # …because sibling bumped to parent to ~50 s/vB, while our target is 30 s/vB
 412          resulting_ancestry_fee_rate_sibling = self.calc_set_fee_rate([parent_tx, sibling_tx])
 413          assert_greater_than_or_equal(resulting_ancestry_fee_rate_sibling, self.target_fee_rate)
 414          # and our resulting "ancestry feerate" is therefore BELOW target feerate
 415          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 416          assert_greater_than_or_equal(self.target_fee_rate, resulting_ancestry_fee_rate)
 417  
 418          wallet.unloadwallet()
 419  
 420      # Spend a confirmed and an unconfirmed input at the same time
 421      def test_confirmed_and_unconfirmed_parent(self):
 422          self.log.info("Start test with one unconfirmed and one confirmed input")
 423          wallet = self.setup_and_fund_wallet("confirmed_and_unconfirmed_wallet")
 424          confirmed_parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=1, fee_rate=self.target_fee_rate)
 425          self.generate(self.nodes[0], 1) # Wallet has two confirmed UTXOs of ~1BTC each
 426          unconfirmed_parent_txid = wallet.sendtoaddress(address=wallet.getnewaddress(), amount=0.5, fee_rate=0.5*self.target_fee_rate)
 427  
 428          # wallet has one confirmed UTXO of 1BTC and two unconfirmed UTXOs of ~0.5BTC each
 429          ancestor_aware_txid = wallet.sendtoaddress(address=self.def_wallet.getnewaddress(), amount=1.4, fee_rate=self.target_fee_rate)
 430          ancestor_aware_tx = wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 431          self.assert_spends_only_parents(ancestor_aware_tx, [confirmed_parent_txid, unconfirmed_parent_txid])
 432          resulting_fee_rate = self.calc_fee_rate(ancestor_aware_tx)
 433          assert_greater_than_or_equal(resulting_fee_rate, self.target_fee_rate)
 434  
 435          wallet.unloadwallet()
 436  
 437      def test_external_input_unconfirmed_low(self):
 438          self.log.info("Send funds to an external wallet then build tx that bumps parent by spending external input")
 439          wallet = self.setup_and_fund_wallet("test_external_wallet")
 440  
 441          external_address = self.def_wallet.getnewaddress()
 442          address_info = self.def_wallet.getaddressinfo(external_address)
 443          external_descriptor = address_info["desc"]
 444          parent_txid = wallet.sendtoaddress(address=external_address, amount=1, fee_rate=1)
 445          parent_tx = wallet.gettransaction(txid=parent_txid, verbose=True)
 446  
 447          self.assert_undershoots_target(parent_tx)
 448  
 449          spend_res = wallet.send(outputs=[{self.def_wallet.getnewaddress(): 0.5}], fee_rate=self.target_fee_rate, options={"inputs":[{"txid":parent_txid, "vout":find_vout_for_address(self.nodes[0], parent_txid, external_address)}], "solving_data":{"descriptors":[external_descriptor]}})
 450          signed_psbt = self.def_wallet.walletprocesspsbt(spend_res["psbt"])
 451          external_tx = self.def_wallet.finalizepsbt(signed_psbt["psbt"])
 452          ancestor_aware_txid = self.def_wallet.sendrawtransaction(external_tx["hex"])
 453  
 454          ancestor_aware_tx = self.def_wallet.gettransaction(txid=ancestor_aware_txid, verbose=True)
 455  
 456          self.assert_spends_only_parents(ancestor_aware_tx, [parent_txid])
 457  
 458          self.assert_beats_target(ancestor_aware_tx)
 459          resulting_ancestry_fee_rate = self.calc_set_fee_rate([parent_tx, ancestor_aware_tx])
 460          assert_greater_than_or_equal(resulting_ancestry_fee_rate, self.target_fee_rate)
 461          assert_greater_than_or_equal(self.target_fee_rate*1.01, resulting_ancestry_fee_rate)
 462  
 463          wallet.unloadwallet()
 464  
 465  
 466      def run_test(self):
 467          self.log.info("Starting UnconfirmedInputTest!")
 468          self.target_fee_rate = 30
 469          self.def_wallet  = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
 470          self.generate(self.nodes[0], 110)
 471  
 472          self.test_target_feerate_confirmed()
 473  
 474          self.test_target_feerate_unconfirmed_high()
 475  
 476          self.test_target_feerate_unconfirmed_low()
 477  
 478          self.test_chain_of_unconfirmed_low()
 479  
 480          self.test_two_low_feerate_unconfirmed_parents()
 481  
 482          self.test_mixed_feerate_unconfirmed_parents()
 483  
 484          self.test_chain_of_high_low()
 485  
 486          self.test_chain_of_high_low_below_target_feerate()
 487  
 488          self.test_target_feerate_unconfirmed_low_sffo()
 489  
 490          self.test_preset_input_cpfp()
 491  
 492          self.test_rbf_bumping()
 493  
 494          self.test_target_feerate_unconfirmed_low_overlapping_ancestry()
 495  
 496          self.test_sibling_tx_gets_ignored()
 497  
 498          self.test_sibling_tx_bumps_parent()
 499  
 500          self.test_confirmed_and_unconfirmed_parent()
 501  
 502          self.test_external_input_unconfirmed_low()
 503  
 504  if __name__ == '__main__':
 505      UnconfirmedInputTest(__file__).main()
 506