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