/ test / functional / wallet_spend_unconfirmed.py
wallet_spend_unconfirmed.py
  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()