wallet_bumpfee.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2016-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  """Test the bumpfee RPC.
   6  
   7  Verifies that the bumpfee RPC creates replacement transactions successfully when
   8  its preconditions are met, and returns appropriate errors in other cases.
   9  
  10  This module consists of around a dozen individual test cases implemented in the
  11  top-level functions named as test_<test_case_description>. The test functions
  12  can be disabled or reordered if needed for debugging. If new test cases are
  13  added in the future, they should try to follow the same convention and not
  14  make assumptions about execution order.
  15  """
  16  from decimal import Decimal
  17  
  18  from test_framework.blocktools import (
  19      COINBASE_MATURITY,
  20  )
  21  from test_framework.descriptors import descsum_create
  22  from test_framework.extendedkey import ExtendedPrivateKey
  23  from test_framework.messages import (
  24      MAX_BIP125_RBF_SEQUENCE,
  25      MAX_SEQUENCE_NONFINAL,
  26  )
  27  from test_framework.test_framework import BitcoinTestFramework
  28  from test_framework.util import (
  29      assert_equal,
  30      assert_fee_amount,
  31      assert_greater_than,
  32      assert_raises_rpc_error,
  33      get_fee,
  34      find_vout_for_address,
  35  )
  36  from test_framework.wallet import MiniWallet
  37  
  38  
  39  WALLET_PASSPHRASE = "test"
  40  WALLET_PASSPHRASE_TIMEOUT = 3600
  41  
  42  # Fee rates (sat/vB)
  43  INSUFFICIENT =      1
  44  ECONOMICAL   =     50
  45  NORMAL       =    100
  46  HIGH         =    500
  47  TOO_HIGH     = 100000
  48  
  49  def get_change_address(tx, node):
  50      tx_details = node.getrawtransaction(tx, 1)
  51      txout_addresses = [txout['scriptPubKey']['address'] for txout in tx_details["vout"]]
  52      return [address for address in txout_addresses if node.getaddressinfo(address)["ischange"]]
  53  
  54  class BumpFeeTest(BitcoinTestFramework):
  55      def set_test_params(self):
  56          self.num_nodes = 2
  57          self.setup_clean_chain = True
  58          # whitelist peers to speed up tx relay / mempool sync
  59          self.noban_tx_relay = True
  60          self.extra_args = [[
  61              "-mintxfee=0.00002",
  62              "-addresstype=bech32",
  63          ] for i in range(self.num_nodes)]
  64  
  65      def skip_test_if_missing_module(self):
  66          self.skip_if_no_wallet()
  67  
  68      def clear_mempool(self):
  69          # Clear mempool between subtests. The subtests may only depend on chainstate (utxos)
  70          self.generate(self.nodes[1], 1)
  71  
  72      def run_test(self):
  73          # Encrypt wallet for test_locked_wallet_fails test
  74          self.nodes[1].encryptwallet(WALLET_PASSPHRASE)
  75          self.nodes[1].walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
  76  
  77          peer_node, rbf_node = self.nodes
  78          rbf_node_address = rbf_node.getnewaddress()
  79  
  80          # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis)
  81          self.log.info("Mining blocks...")
  82          self.generate(peer_node, 110)
  83          for _ in range(25):
  84              peer_node.sendtoaddress(rbf_node_address, 0.001)
  85          self.sync_all()
  86          self.generate(peer_node, 1)
  87          assert_equal(rbf_node.getbalance(), Decimal("0.025"))
  88  
  89          self.log.info("Running tests")
  90          dest_address = peer_node.getnewaddress()
  91          for mode in ["default", "fee_rate", "new_outputs"]:
  92              test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address)
  93          self.test_invalid_parameters(rbf_node, peer_node, dest_address)
  94          test_segwit_bumpfee_succeeds(self, rbf_node, dest_address)
  95          test_nonrbf_bumpfee_succeeds(self, peer_node, dest_address)
  96          test_notmine_bumpfee(self, rbf_node, peer_node, dest_address)
  97          test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address)
  98          test_bumpfee_with_abandoned_descendant_succeeds(self, rbf_node, rbf_node_address, dest_address)
  99          test_dust_to_fee(self, rbf_node, dest_address)
 100          test_watchonly_psbt(self, peer_node, rbf_node, dest_address)
 101          test_rebumping(self, rbf_node, dest_address)
 102          test_rebumping_not_replaceable(self, rbf_node, dest_address)
 103          test_bumpfee_already_spent(self, rbf_node, dest_address)
 104          test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address)
 105          test_bumpfee_metadata(self, rbf_node, dest_address)
 106          test_locked_wallet_fails(self, rbf_node, dest_address)
 107          test_change_script_match(self, rbf_node, dest_address)
 108          test_maxtxfee_fails(self, rbf_node, dest_address)
 109          # These tests wipe out a number of utxos that are expected in other tests
 110          test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
 111          test_no_more_inputs_fails(self, rbf_node, dest_address)
 112          self.test_bump_back_to_yourself()
 113          self.test_provided_change_pos(rbf_node)
 114          self.test_single_output()
 115  
 116          # Context independent tests
 117          test_feerate_checks_replaced_outputs(self, rbf_node, peer_node)
 118          test_bumpfee_with_feerate_ignores_walletincrementalrelayfee(self, rbf_node, peer_node)
 119  
 120      def test_invalid_parameters(self, rbf_node, peer_node, dest_address):
 121          self.log.info('Test invalid parameters')
 122          rbfid = spend_one_input(rbf_node, dest_address)
 123          self.sync_mempools((rbf_node, peer_node))
 124          assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
 125  
 126          for key in ["totalFee", "feeRate"]:
 127              assert_raises_rpc_error(-3, "Unexpected key {}".format(key), rbf_node.bumpfee, rbfid, {key: NORMAL})
 128  
 129          # Bumping to just above minrelay should fail to increase the total fee enough.
 130          assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141", rbf_node.bumpfee, rbfid, fee_rate=INSUFFICIENT)
 131  
 132          self.log.info("Test invalid fee rate settings")
 133          assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10",
 134              rbf_node.bumpfee, rbfid, fee_rate=TOO_HIGH)
 135          # Test fee_rate with zero values.
 136          msg = "Insufficient total fee 0.00"
 137          for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]:
 138              assert_raises_rpc_error(-8, msg, rbf_node.bumpfee, rbfid, fee_rate=zero_value)
 139          msg = "Invalid amount"
 140          # Test fee_rate values that don't pass fixed-point parsing checks.
 141          if not self.options.usecli:
 142              for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
 143                  assert_raises_rpc_error(-3, msg, rbf_node.bumpfee, rbfid, fee_rate=invalid_value)
 144          # Test fee_rate values that cannot be represented in sat/vB.
 145          for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
 146              assert_raises_rpc_error(-3, msg, rbf_node.bumpfee, rbfid, fee_rate=invalid_value)
 147          # Test fee_rate out of range (negative number).
 148          assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, fee_rate=-1)
 149          # Test type error.
 150          for value in [{"foo": "bar"}, True]:
 151              assert_raises_rpc_error(-3, "Amount is not a number or string", rbf_node.bumpfee, rbfid, fee_rate=value)
 152  
 153          self.log.info("Test explicit fee rate raises RPC error if both fee_rate and conf_target are passed")
 154          assert_raises_rpc_error(-8, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation "
 155              "target in blocks for automatic fee estimation, or an explicit fee rate.",
 156              rbf_node.bumpfee, rbfid, conf_target=NORMAL, fee_rate=NORMAL)
 157  
 158          self.log.info("Test explicit fee rate raises RPC error if both fee_rate and estimate_mode are passed")
 159          assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate",
 160              rbf_node.bumpfee, rbfid, estimate_mode="economical", fee_rate=NORMAL)
 161  
 162          self.log.info("Test invalid conf_target settings")
 163          assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set",
 164              rbf_node.bumpfee, rbfid, {"confTarget": 123, "conf_target": 456})
 165  
 166          self.log.info("Test invalid estimate_mode settings")
 167          if not self.options.usecli:
 168              for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
 169                  assert_raises_rpc_error(-3, f"JSON value of type {k} for field estimate_mode is not of expected type string",
 170                      rbf_node.bumpfee, rbfid, estimate_mode=v)
 171          for mode in ["foo", Decimal("3.1415"), "sat/B", "BTC/kB"]:
 172              assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
 173                  rbf_node.bumpfee, rbfid, estimate_mode=mode)
 174  
 175          self.log.info("Test invalid outputs values")
 176          assert_raises_rpc_error(-8, "Invalid parameter, output argument cannot be an empty array",
 177                  rbf_node.bumpfee, rbfid, {"outputs": []})
 178          assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: " + dest_address,
 179                  rbf_node.bumpfee, rbfid, {"outputs": [{dest_address: 0.1}, {dest_address: 0.2}]})
 180          assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data",
 181                  rbf_node.bumpfee, rbfid, {"outputs": [{"data": "deadbeef"}, {"data": "deadbeef"}]})
 182  
 183          self.log.info("Test original_change_index option")
 184          assert_raises_rpc_error(-1, "JSON integer out of range", rbf_node.bumpfee, rbfid, {"original_change_index": -1})
 185          assert_raises_rpc_error(-8, "Change position is out of range", rbf_node.bumpfee, rbfid, {"original_change_index": 2})
 186  
 187          self.log.info("Test outputs and original_change_index cannot both be provided")
 188          assert_raises_rpc_error(-8, "The options 'outputs' and 'original_change_index' are incompatible. You can only either specify a new set of outputs, or designate a change output to be recycled.", rbf_node.bumpfee, rbfid, {"original_change_index": 2, "outputs": [{dest_address: 0.1}]})
 189  
 190          self.clear_mempool()
 191  
 192      def test_bump_back_to_yourself(self):
 193          self.log.info("Test that bumpfee can send coins back to yourself")
 194          node = self.nodes[1]
 195  
 196          node.createwallet("back_to_yourself")
 197          wallet = node.get_wallet_rpc("back_to_yourself")
 198  
 199          # Make 3 UTXOs
 200          addr = wallet.getnewaddress()
 201          for _ in range(3):
 202              self.nodes[0].sendtoaddress(addr, 5)
 203          self.generate(self.nodes[0], 1)
 204  
 205          # Create a tx with two outputs. recipient and change.
 206          tx = wallet.send(outputs={wallet.getnewaddress(): 9}, fee_rate=2)
 207          tx_info = wallet.gettransaction(txid=tx["txid"], verbose=True)
 208          assert_equal(len(tx_info["decoded"]["vout"]), 2)
 209          assert_equal(len(tx_info["decoded"]["vin"]), 2)
 210  
 211          # Bump tx, send coins back to change address.
 212          change_addr = get_change_address(tx["txid"], wallet)[0]
 213          out_amount = 10
 214          bumped = wallet.bumpfee(txid=tx["txid"], options={"fee_rate": 20, "outputs": [{change_addr: out_amount}]})
 215          bumped_tx = wallet.gettransaction(txid=bumped["txid"], verbose=True)
 216          assert_equal(len(bumped_tx["decoded"]["vout"]), 1)
 217          assert_equal(len(bumped_tx["decoded"]["vin"]), 2)
 218          assert_equal(bumped_tx["decoded"]["vout"][0]["value"] + bumped["fee"], out_amount)
 219  
 220          # Bump tx again, now test send fewer coins back to change address.
 221          out_amount = 6
 222          bumped = wallet.bumpfee(txid=bumped["txid"], options={"fee_rate": 40, "outputs": [{change_addr: out_amount}]})
 223          bumped_tx = wallet.gettransaction(txid=bumped["txid"], verbose=True)
 224          assert_equal(len(bumped_tx["decoded"]["vout"]), 2)
 225          assert_equal(len(bumped_tx["decoded"]["vin"]), 2)
 226          assert any(txout['value'] == out_amount - bumped["fee"] and txout['scriptPubKey']['address'] == change_addr for txout in bumped_tx['decoded']['vout'])
 227          # Check that total out amount is still equal to the previously bumped tx
 228          assert_equal(bumped_tx["decoded"]["vout"][0]["value"] + bumped_tx["decoded"]["vout"][1]["value"] + bumped["fee"], 10)
 229  
 230          # Bump tx again, send more coins back to change address. The process will add another input to cover the target.
 231          out_amount = 12
 232          bumped = wallet.bumpfee(txid=bumped["txid"], options={"fee_rate": 80, "outputs": [{change_addr: out_amount}]})
 233          bumped_tx = wallet.gettransaction(txid=bumped["txid"], verbose=True)
 234          assert_equal(len(bumped_tx["decoded"]["vout"]), 2)
 235          assert_equal(len(bumped_tx["decoded"]["vin"]), 3)
 236          assert any(txout['value'] == out_amount - bumped["fee"] and txout['scriptPubKey']['address'] == change_addr for txout in bumped_tx['decoded']['vout'])
 237          assert_equal(bumped_tx["decoded"]["vout"][0]["value"] + bumped_tx["decoded"]["vout"][1]["value"] + bumped["fee"], 15)
 238  
 239          node.unloadwallet("back_to_yourself")
 240  
 241      def test_provided_change_pos(self, rbf_node):
 242          self.log.info("Test the original_change_index option")
 243  
 244          change_addr = rbf_node.getnewaddress()
 245          dest_addr = rbf_node.getnewaddress()
 246          assert_equal(rbf_node.getaddressinfo(change_addr)["ischange"], False)
 247          assert_equal(rbf_node.getaddressinfo(dest_addr)["ischange"], False)
 248  
 249          send_res = rbf_node.send(outputs=[{dest_addr: 1}], options={"change_address": change_addr})
 250          assert send_res["complete"]
 251          txid = send_res["txid"]
 252  
 253          tx = rbf_node.gettransaction(txid=txid, verbose=True)
 254          assert_equal(len(tx["decoded"]["vout"]), 2)
 255  
 256          change_pos = find_vout_for_address(rbf_node, txid, change_addr)
 257          change_value = tx["decoded"]["vout"][change_pos]["value"]
 258  
 259          bumped = rbf_node.bumpfee(txid, {"original_change_index": change_pos})
 260          new_txid = bumped["txid"]
 261  
 262          new_tx = rbf_node.gettransaction(txid=new_txid, verbose=True)
 263          assert_equal(len(new_tx["decoded"]["vout"]), 2)
 264          new_change_pos = find_vout_for_address(rbf_node, new_txid, change_addr)
 265          new_change_value = new_tx["decoded"]["vout"][new_change_pos]["value"]
 266  
 267          assert_greater_than(change_value, new_change_value)
 268  
 269  
 270      def test_single_output(self):
 271          self.log.info("Test that single output txs can be bumped")
 272          node = self.nodes[1]
 273  
 274          node.createwallet("single_out_rbf")
 275          wallet = node.get_wallet_rpc("single_out_rbf")
 276  
 277          addr = wallet.getnewaddress()
 278          amount = Decimal("0.001")
 279          # Make 2 UTXOs
 280          self.nodes[0].sendtoaddress(addr, amount)
 281          self.nodes[0].sendtoaddress(addr, amount)
 282          self.generate(self.nodes[0], 1)
 283          utxos = wallet.listunspent()
 284  
 285          tx = wallet.sendall(recipients=[wallet.getnewaddress()], fee_rate=2, options={"inputs": [utxos[0]]})
 286  
 287          # Set the only output with a crazy high feerate as change, should fail as the output would be dust
 288          assert_raises_rpc_error(-4, "The transaction amount is too small to pay the fee", wallet.bumpfee, txid=tx["txid"], options={"fee_rate": 1100, "original_change_index": 0})
 289  
 290          # Specify single output as change successfully
 291          bumped = wallet.bumpfee(txid=tx["txid"], options={"fee_rate": 10, "original_change_index": 0})
 292          bumped_tx = wallet.gettransaction(txid=bumped["txid"], verbose=True)
 293          assert_equal(len(bumped_tx["decoded"]["vout"]), 1)
 294          assert_equal(len(bumped_tx["decoded"]["vin"]), 1)
 295          assert_equal(bumped_tx["decoded"]["vout"][0]["value"] + bumped["fee"], amount)
 296          assert_fee_amount(bumped["fee"], bumped_tx["decoded"]["vsize"], Decimal(10) / Decimal(1e8) * 1000)
 297  
 298          # Bumping without specifying change adds a new input and output
 299          bumped = wallet.bumpfee(txid=bumped["txid"], options={"fee_rate": 20})
 300          bumped_tx = wallet.gettransaction(txid=bumped["txid"], verbose=True)
 301          assert_equal(len(bumped_tx["decoded"]["vout"]), 2)
 302          assert_equal(len(bumped_tx["decoded"]["vin"]), 2)
 303          assert_fee_amount(bumped["fee"], bumped_tx["decoded"]["vsize"], Decimal(20) / Decimal(1e8) * 1000)
 304  
 305          wallet.unloadwallet()
 306  
 307  def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
 308      self.log.info('Test simple bumpfee: {}'.format(mode))
 309      rbfid = spend_one_input(rbf_node, dest_address)
 310      rbftx = rbf_node.gettransaction(rbfid)
 311      self.sync_mempools((rbf_node, peer_node))
 312      assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
 313      if mode == "fee_rate":
 314          bumped_psbt = rbf_node.psbtbumpfee(rbfid, fee_rate=str(NORMAL))
 315          bumped_tx = rbf_node.bumpfee(rbfid, fee_rate=NORMAL)
 316      elif mode == "new_outputs":
 317          new_address = peer_node.getnewaddress()
 318          bumped_psbt = rbf_node.psbtbumpfee(rbfid, outputs={new_address: 0.0003})
 319          bumped_tx = rbf_node.bumpfee(rbfid, outputs={new_address: 0.0003})
 320      else:
 321          bumped_psbt = rbf_node.psbtbumpfee(rbfid)
 322          bumped_tx = rbf_node.bumpfee(rbfid)
 323      assert_equal(bumped_tx["errors"], [])
 324      assert bumped_tx["fee"] > -rbftx["fee"]
 325      assert_equal(bumped_tx["origfee"], -rbftx["fee"])
 326      assert "psbt" not in bumped_tx
 327      assert_equal(bumped_psbt["errors"], [])
 328      assert bumped_psbt["fee"] > -rbftx["fee"]
 329      assert_equal(bumped_psbt["origfee"], -rbftx["fee"])
 330      assert "psbt" in bumped_psbt
 331      # check that bumped_tx propagates, original tx was evicted and has a wallet conflict
 332      self.sync_mempools((rbf_node, peer_node))
 333      assert bumped_tx["txid"] in rbf_node.getrawmempool()
 334      assert bumped_tx["txid"] in peer_node.getrawmempool()
 335      assert rbfid not in rbf_node.getrawmempool()
 336      assert rbfid not in peer_node.getrawmempool()
 337      oldwtx = rbf_node.gettransaction(rbfid)
 338      assert len(oldwtx["walletconflicts"]) > 0
 339      # check wallet transaction replaces and replaced_by values
 340      bumpedwtx = rbf_node.gettransaction(bumped_tx["txid"])
 341      assert_equal(oldwtx["replaced_by_txid"], bumped_tx["txid"])
 342      assert_equal(bumpedwtx["replaces_txid"], rbfid)
 343      # if this is a new_outputs test, check that outputs were indeed replaced
 344      if mode == "new_outputs":
 345          assert_equal(len(bumpedwtx["details"]), 1)
 346          assert_equal(bumpedwtx["details"][0]["address"], new_address)
 347      self.clear_mempool()
 348  
 349  
 350  def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address):
 351      self.log.info('Test that segwit-sourcing bumpfee works')
 352      # Create a transaction with segwit output, then create an RBF transaction
 353      # which spends it, and make sure bumpfee can be called on it.
 354  
 355      segwit_out = rbf_node.getnewaddress(address_type='bech32')
 356      segwitid = rbf_node.send({segwit_out: "0.0009"}, options={"change_position": 1})["txid"]
 357  
 358      rbfraw = rbf_node.createrawtransaction([{
 359          'txid': segwitid,
 360          'vout': 0,
 361          "sequence": MAX_BIP125_RBF_SEQUENCE
 362      }], {dest_address: Decimal("0.0005"),
 363           rbf_node.getrawchangeaddress(): Decimal("0.0003")})
 364      rbfsigned = rbf_node.signrawtransactionwithwallet(rbfraw)
 365      rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"])
 366      assert rbfid in rbf_node.getrawmempool()
 367  
 368      bumped_tx = rbf_node.bumpfee(rbfid)
 369      assert bumped_tx["txid"] in rbf_node.getrawmempool()
 370      assert rbfid not in rbf_node.getrawmempool()
 371      self.clear_mempool()
 372  
 373  
 374  def test_nonrbf_bumpfee_succeeds(self, peer_node, dest_address):
 375      self.log.info("Test that we can replace a non RBF transaction")
 376      not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000"))
 377      peer_node.bumpfee(not_rbfid)
 378      self.clear_mempool()
 379  
 380  
 381  def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address):
 382      self.log.info('Test that it cannot bump fee if non-owned inputs are included')
 383      # here, the rbftx has a peer_node coin and then adds a rbf_node input
 384      # Note that this test depends upon the RPC code checking input ownership prior to change outputs
 385      # (since it can't use fundrawtransaction, it lacks a proper change output)
 386      fee = Decimal("0.001")
 387      utxos = [node.listunspent(minimumAmount=fee)[-1] for node in (rbf_node, peer_node)]
 388      inputs = [{
 389          "txid": utxo["txid"],
 390          "vout": utxo["vout"],
 391          "address": utxo["address"],
 392          "sequence": MAX_BIP125_RBF_SEQUENCE
 393      } for utxo in utxos]
 394      output_val = sum(utxo["amount"] for utxo in utxos) - fee
 395      rawtx = rbf_node.createrawtransaction(inputs, {dest_address: output_val})
 396      signedtx = rbf_node.signrawtransactionwithwallet(rawtx)
 397      signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"])
 398      rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
 399      entry = rbf_node.getmempoolentry(rbfid)
 400      old_fee = entry["fees"]["base"]
 401      old_feerate = int(old_fee / entry["vsize"] * Decimal(1e8))
 402      assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
 403                              rbf_node.bumpfee, rbfid)
 404  
 405      def finish_psbtbumpfee(psbt):
 406          psbt = rbf_node.walletprocesspsbt(psbt)
 407          psbt = peer_node.walletprocesspsbt(psbt["psbt"])
 408          res = rbf_node.testmempoolaccept([psbt["hex"]])
 409          assert res[0]["allowed"]
 410          assert_greater_than(res[0]["fees"]["base"], old_fee)
 411  
 412      self.log.info("Test that psbtbumpfee works for non-owned inputs")
 413      psbt = rbf_node.psbtbumpfee(txid=rbfid)
 414      finish_psbtbumpfee(psbt["psbt"])
 415  
 416      psbt = rbf_node.psbtbumpfee(txid=rbfid, fee_rate=old_feerate + 10)
 417      finish_psbtbumpfee(psbt["psbt"])
 418  
 419      self.clear_mempool()
 420  
 421  
 422  def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address):
 423      self.log.info('Test that fee cannot be bumped when it has descendant')
 424      # parent is send-to-self, so we don't have to check which output is change when creating the child tx
 425      parent_id = spend_one_input(rbf_node, rbf_node_address)
 426      tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000})
 427      tx = rbf_node.signrawtransactionwithwallet(tx)
 428      rbf_node.sendrawtransaction(tx["hex"])
 429      assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
 430  
 431      # create tx with descendant in the mempool by using MiniWallet
 432      miniwallet = MiniWallet(rbf_node)
 433      parent_id = spend_one_input(rbf_node, miniwallet.get_address())
 434      tx = rbf_node.gettransaction(txid=parent_id, verbose=True)['decoded']
 435      miniwallet.scan_tx(tx)
 436      miniwallet.send_self_transfer(from_node=rbf_node)
 437      assert_raises_rpc_error(-8, "Transaction has descendants in the mempool", rbf_node.bumpfee, parent_id)
 438      self.clear_mempool()
 439  
 440  
 441  def test_bumpfee_with_abandoned_descendant_succeeds(self, rbf_node, rbf_node_address, dest_address):
 442      self.log.info('Test that fee can be bumped when it has abandoned descendant')
 443      # parent is send-to-self, so we don't have to check which output is change when creating the child tx
 444      parent_id = spend_one_input(rbf_node, rbf_node_address)
 445      # Submit child transaction with low fee
 446      child_id = rbf_node.send(outputs={dest_address: 0.00020000},
 447                               options={"inputs": [{"txid": parent_id, "vout": 0}], "fee_rate": 2})["txid"]
 448      assert child_id in rbf_node.getrawmempool()
 449  
 450      # Restart the node with higher min relay fee so the descendant tx is no longer in mempool so that we can abandon it
 451      self.restart_node(1, ['-minrelaytxfee=0.00005'] + self.extra_args[1])
 452      rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
 453      self.connect_nodes(1, 0)
 454      assert parent_id in rbf_node.getrawmempool()
 455      assert child_id not in rbf_node.getrawmempool()
 456      # Should still raise an error even if not in mempool
 457      assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id)
 458      # Now abandon the child transaction and bump the original
 459      rbf_node.abandontransaction(child_id)
 460      bumped_result = rbf_node.bumpfee(parent_id, {"fee_rate": HIGH})
 461      assert bumped_result['txid'] in rbf_node.getrawmempool()
 462      assert parent_id not in rbf_node.getrawmempool()
 463      # Cleanup
 464      self.restart_node(1, self.extra_args[1])
 465      rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
 466      self.connect_nodes(1, 0)
 467      self.clear_mempool()
 468  
 469  
 470  def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address):
 471      self.log.info('Testing small output with feerate bump succeeds')
 472  
 473      # Make sure additional inputs exist
 474      self.generatetoaddress(rbf_node, COINBASE_MATURITY + 1, rbf_node.getnewaddress())
 475      rbfid = spend_one_input(rbf_node, dest_address)
 476      input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
 477      assert_equal(len(input_list), 1)
 478      original_txin = input_list[0]
 479      self.log.info('Keep bumping until transaction fee out-spends non-destination value')
 480      tx_fee = 0
 481      while True:
 482          input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
 483          new_item = list(input_list)[0]
 484          assert_equal(len(input_list), 1)
 485          assert_equal(original_txin["txid"], new_item["txid"])
 486          assert_equal(original_txin["vout"], new_item["vout"])
 487          rbfid_new_details = rbf_node.bumpfee(rbfid)
 488          rbfid_new = rbfid_new_details["txid"]
 489          raw_pool = rbf_node.getrawmempool()
 490          assert rbfid not in raw_pool
 491          assert rbfid_new in raw_pool
 492          rbfid = rbfid_new
 493          tx_fee = rbfid_new_details["fee"]
 494  
 495          # Total value from input not going to destination
 496          if tx_fee > Decimal('0.00050000'):
 497              break
 498  
 499      # input(s) have been added
 500      final_input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"]
 501      assert_greater_than(len(final_input_list), 1)
 502      # Original input is in final set
 503      assert [txin for txin in final_input_list
 504              if txin["txid"] == original_txin["txid"]
 505              and txin["vout"] == original_txin["vout"]]
 506  
 507      self.generatetoaddress(rbf_node, 1, rbf_node.getnewaddress())
 508      assert_equal(rbf_node.gettransaction(rbfid)["confirmations"], 1)
 509      self.clear_mempool()
 510  
 511  
 512  def test_dust_to_fee(self, rbf_node, dest_address):
 513      self.log.info('Test that bumped output that is dust is dropped to fee')
 514      rbfid = spend_one_input(rbf_node, dest_address)
 515      fulltx = rbf_node.getrawtransaction(rbfid, 1)
 516      # The DER formatting used by Bitcoin to serialize ECDSA signatures means that signatures can have a
 517      # variable size of 70-72 bytes (or possibly even less), with most being 71 or 72 bytes. The signature
 518      # in the witness is divided by 4 for the vsize, so this variance can take the weight across a 4-byte
 519      # boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141.
 520      if not 140 <= fulltx["vsize"] <= 141:
 521          raise AssertionError("Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx))
 522      # Bump with fee_rate of 350.25 sat/vB vbytes to create dust.
 523      # Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC.
 524      # or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC.
 525      # Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC.
 526      bumped_tx = rbf_node.bumpfee(rbfid, fee_rate=350.25)
 527      full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
 528      assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
 529      assert_equal(len(fulltx["vout"]), 2)
 530      assert_equal(len(full_bumped_tx["vout"]), 1)  # change output is eliminated
 531      assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000"))
 532      self.clear_mempool()
 533  
 534  def test_maxtxfee_fails(self, rbf_node, dest_address):
 535      self.log.info('Test that bumpfee fails when it hits -maxtxfee')
 536      # size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes
 537      # expected bump fee of 141 vbytes * 0.00200000 BTC / 1000 vbytes = 0.00002820 BTC
 538      # which exceeds maxtxfee and is expected to raise
 539      self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1])
 540      rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
 541      rbfid = spend_one_input(rbf_node, dest_address)
 542      assert_raises_rpc_error(-4, "Unable to create transaction. Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", rbf_node.bumpfee, rbfid)
 543      self.restart_node(1, self.extra_args[1])
 544      rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
 545      self.connect_nodes(1, 0)
 546      self.clear_mempool()
 547  
 548  
 549  def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
 550      self.log.info('Test that PSBT is returned for bumpfee in watchonly wallets')
 551      priv_rec_desc = descsum_create(f"wpkh([00000001/84'/1'/0']{ExtendedPrivateKey.generate().to_string()}/0/*)")
 552      pub_rec_desc = rbf_node.getdescriptorinfo(priv_rec_desc)["descriptor"]
 553      priv_change_desc = descsum_create(f"wpkh([00000001/84'/1'/0']{ExtendedPrivateKey.generate().to_string()}/1/*)")
 554      pub_change_desc = rbf_node.getdescriptorinfo(priv_change_desc)["descriptor"]
 555      # Create a wallet with private keys that can sign PSBTs
 556      rbf_node.createwallet(wallet_name="signer", disable_private_keys=False, blank=True)
 557      signer = rbf_node.get_wallet_rpc("signer")
 558      assert signer.getwalletinfo()['private_keys_enabled']
 559      reqs = [{
 560          "desc": priv_rec_desc,
 561          "timestamp": 0,
 562          "range": [0,1],
 563          "internal": False,
 564          "keypool": False # Keys can only be imported to the keypool when private keys are disabled
 565      },
 566      {
 567          "desc": priv_change_desc,
 568          "timestamp": 0,
 569          "range": [0, 0],
 570          "internal": True,
 571          "keypool": False
 572      }]
 573      result = signer.importdescriptors(reqs)
 574      assert_equal(result, [{'success': True}, {'success': True}])
 575  
 576      # Create another wallet with just the public keys, which creates PSBTs
 577      rbf_node.createwallet(wallet_name="watcher", disable_private_keys=True, blank=True)
 578      watcher = rbf_node.get_wallet_rpc("watcher")
 579      assert not watcher.getwalletinfo()['private_keys_enabled']
 580  
 581      reqs = [{
 582          "desc": pub_rec_desc,
 583          "timestamp": 0,
 584          "range": [0, 10],
 585          "internal": False,
 586          "keypool": True,
 587          "watchonly": True,
 588          "active": True,
 589      }, {
 590          "desc": pub_change_desc,
 591          "timestamp": 0,
 592          "range": [0, 10],
 593          "internal": True,
 594          "keypool": True,
 595          "watchonly": True,
 596          "active": True,
 597      }]
 598      result = watcher.importdescriptors(reqs)
 599      assert_equal(result, [{'success': True}, {'success': True}])
 600  
 601      funding_address1 = watcher.getnewaddress(address_type='bech32')
 602      funding_address2 = watcher.getnewaddress(address_type='bech32')
 603      peer_node.sendmany("", {funding_address1: 0.001, funding_address2: 0.001})
 604      self.generate(peer_node, 1)
 605  
 606      # Create single-input PSBT for transaction to be bumped
 607      # Ensure the payment amount + change can be fully funded using one of the 0.001BTC inputs.
 608      psbt = watcher.walletcreatefundedpsbt([watcher.listunspent()[0]], {dest_address: 0.0005}, 0,
 609              {"fee_rate": 1, "add_inputs": False}, True)['psbt']
 610      psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True)
 611      original_txid = watcher.sendrawtransaction(psbt_signed["hex"])
 612      assert_equal(len(watcher.decodepsbt(psbt)["inputs"]), 1)
 613  
 614      # bumpfee can't be used on watchonly wallets
 615      assert_raises_rpc_error(-4, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead.", watcher.bumpfee, original_txid)
 616  
 617      # Bump fee, obnoxiously high to add additional watchonly input
 618      bumped_psbt = watcher.psbtbumpfee(original_txid, fee_rate=HIGH)
 619      assert_greater_than(len(watcher.decodepsbt(bumped_psbt['psbt'])["inputs"]), 1)
 620      assert "txid" not in bumped_psbt
 621      assert_equal(bumped_psbt["origfee"], -watcher.gettransaction(original_txid)["fee"])
 622      assert not watcher.finalizepsbt(bumped_psbt["psbt"])["complete"]
 623  
 624      # Sign bumped transaction
 625      bumped_psbt_signed = signer.walletprocesspsbt(psbt=bumped_psbt["psbt"], sign=True, sighashtype="ALL", bip32derivs=True)
 626      assert bumped_psbt_signed["complete"]
 627  
 628      # Broadcast bumped transaction
 629      bumped_txid = watcher.sendrawtransaction(bumped_psbt_signed["hex"])
 630      assert bumped_txid in rbf_node.getrawmempool()
 631      assert original_txid not in rbf_node.getrawmempool()
 632  
 633      rbf_node.unloadwallet("watcher")
 634      rbf_node.unloadwallet("signer")
 635      self.clear_mempool()
 636  
 637  
 638  def test_rebumping(self, rbf_node, dest_address):
 639      self.log.info('Test that re-bumping the original tx fails, but bumping successor works')
 640      rbfid = spend_one_input(rbf_node, dest_address)
 641      bumped = rbf_node.bumpfee(rbfid, fee_rate=ECONOMICAL)
 642      assert_raises_rpc_error(-4, f"Cannot bump transaction {rbfid} which was already bumped by transaction {bumped['txid']}",
 643                              rbf_node.bumpfee, rbfid, fee_rate=NORMAL)
 644      rbf_node.bumpfee(bumped["txid"], fee_rate=NORMAL)
 645      self.clear_mempool()
 646  
 647  
 648  def test_rebumping_not_replaceable(self, rbf_node, dest_address):
 649      self.log.info("Test that re-bumping non-replaceable passes")
 650      rbfid = spend_one_input(rbf_node, dest_address)
 651  
 652      def check_sequence(tx, seq_in):
 653          tx = rbf_node.getrawtransaction(tx["txid"])
 654          tx = rbf_node.decoderawtransaction(tx)
 655          seq = [i["sequence"] for i in tx["vin"]]
 656          assert_equal(seq, [seq_in])
 657  
 658      bumped = rbf_node.bumpfee(rbfid, fee_rate=ECONOMICAL, replaceable=False)
 659      check_sequence(bumped, MAX_SEQUENCE_NONFINAL)
 660      bumped = rbf_node.bumpfee(bumped["txid"], {"fee_rate": NORMAL})
 661      check_sequence(bumped, MAX_BIP125_RBF_SEQUENCE)
 662  
 663      self.clear_mempool()
 664  
 665  
 666  def test_bumpfee_already_spent(self, rbf_node, dest_address):
 667      self.log.info('Test that bumping tx with already spent coin fails')
 668      txid = spend_one_input(rbf_node, dest_address)
 669      self.generate(rbf_node, 1)  # spend coin simply by mining block with tx
 670      spent_input = rbf_node.gettransaction(txid=txid, verbose=True)['decoded']['vin'][0]
 671      assert_raises_rpc_error(-1, f"{spent_input['txid']}:{spent_input['vout']} is already spent",
 672                              rbf_node.bumpfee, txid, fee_rate=NORMAL)
 673  
 674  
 675  def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address):
 676      self.log.info('Test that unconfirmed outputs from bumped txns are not spendable')
 677      rbfid = spend_one_input(rbf_node, rbf_node_address)
 678      rbftx = rbf_node.gettransaction(rbfid)["hex"]
 679      assert rbfid in rbf_node.getrawmempool()
 680      bumpid = rbf_node.bumpfee(rbfid)["txid"]
 681      assert bumpid in rbf_node.getrawmempool()
 682      assert rbfid not in rbf_node.getrawmempool()
 683  
 684      # check that outputs from the bump transaction are not spendable
 685      # due to the replaces_txid check in CWallet::AvailableCoins
 686      assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == bumpid], [])
 687  
 688      # submit a block with the rbf tx to clear the bump tx out of the mempool,
 689      # then invalidate the block so the rbf tx will be put back in the mempool.
 690      # This makes it possible to check whether the rbf tx outputs are
 691      # spendable before the rbf tx is confirmed.
 692      block = self.generateblock(rbf_node, output="raw(51)", transactions=[rbftx])
 693      # Can not abandon conflicted tx
 694      assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: rbf_node.abandontransaction(txid=bumpid))
 695      rbf_node.invalidateblock(block["hash"])
 696      # Call abandon to make sure the wallet doesn't attempt to resubmit
 697      # the bump tx and hope the wallet does not rebroadcast before we call.
 698      rbf_node.abandontransaction(bumpid)
 699  
 700      tx_bump_abandoned = rbf_node.gettransaction(bumpid)
 701      for tx in tx_bump_abandoned['details']:
 702          assert_equal(tx['abandoned'], True)
 703  
 704      assert bumpid not in rbf_node.getrawmempool()
 705      assert rbfid in rbf_node.getrawmempool()
 706  
 707      # check that outputs from the rbf tx are not spendable before the
 708      # transaction is confirmed, due to the replaced_by_txid check in
 709      # CWallet::AvailableCoins
 710      assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == rbfid], [])
 711  
 712      # check that the main output from the rbf tx is spendable after confirmed
 713      self.generate(rbf_node, 1, sync_fun=self.no_op)
 714      assert_equal(
 715          sum(1 for t in rbf_node.listunspent(minconf=0, include_unsafe=False)
 716              if t["txid"] == rbfid and t["address"] == rbf_node_address and t["spendable"]), 1)
 717      self.clear_mempool()
 718  
 719  
 720  def test_bumpfee_metadata(self, rbf_node, dest_address):
 721      self.log.info('Test that bumped txn metadata persists to new txn record')
 722      assert rbf_node.getbalance() < 49
 723      self.generatetoaddress(rbf_node, 101, rbf_node.getnewaddress())
 724      rbfid = rbf_node.sendtoaddress(dest_address, 49, "comment value", "to value")
 725      bumped_tx = rbf_node.bumpfee(rbfid)
 726      bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"])
 727      assert_equal(bumped_wtx["comment"], "comment value")
 728      assert_equal(bumped_wtx["to"], "to value")
 729      self.clear_mempool()
 730  
 731  
 732  def test_locked_wallet_fails(self, rbf_node, dest_address):
 733      self.log.info('Test that locked wallet cannot bump txn')
 734      rbfid = spend_one_input(rbf_node, dest_address)
 735      rbf_node.walletlock()
 736      assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
 737                              rbf_node.bumpfee, rbfid)
 738      rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT)
 739      self.clear_mempool()
 740  
 741  
 742  def test_change_script_match(self, rbf_node, dest_address):
 743      self.log.info('Test that the same change addresses is used for the replacement transaction when possible')
 744  
 745      # Check that there is only one change output
 746      rbfid = spend_one_input(rbf_node, dest_address)
 747      change_addresses = get_change_address(rbfid, rbf_node)
 748      assert_equal(len(change_addresses), 1)
 749  
 750      # Now find that address in each subsequent tx, and no other change
 751      bumped_total_tx = rbf_node.bumpfee(rbfid, fee_rate=ECONOMICAL)
 752      assert_equal(change_addresses, get_change_address(bumped_total_tx['txid'], rbf_node))
 753      bumped_rate_tx = rbf_node.bumpfee(bumped_total_tx["txid"])
 754      assert_equal(change_addresses, get_change_address(bumped_rate_tx['txid'], rbf_node))
 755      self.clear_mempool()
 756  
 757  
 758  def spend_one_input(node, dest_address, change_size=Decimal("0.00049000"), data=None):
 759      tx_input = dict(
 760          sequence=MAX_BIP125_RBF_SEQUENCE, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
 761      destinations = {dest_address: Decimal("0.00050000")}
 762      if change_size > 0:
 763          destinations[node.getrawchangeaddress()] = change_size
 764      if data:
 765          destinations['data'] = data
 766      rawtx = node.createrawtransaction([tx_input], destinations)
 767      signedtx = node.signrawtransactionwithwallet(rawtx)
 768      txid = node.sendrawtransaction(signedtx["hex"])
 769      return txid
 770  
 771  
 772  def test_no_more_inputs_fails(self, rbf_node, dest_address):
 773      self.log.info('Test that bumpfee fails when there are no available confirmed outputs')
 774      # feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient
 775      self.generatetoaddress(rbf_node, 1, dest_address)
 776      # spend all funds, no change output
 777      rbfid = rbf_node.sendall(recipients=[rbf_node.getnewaddress()])['txid']
 778      assert_raises_rpc_error(-4, "Unable to create transaction. The total exceeds your balance when the 0.00001051 transaction fee is included.", rbf_node.bumpfee, rbfid)
 779      self.clear_mempool()
 780  
 781  
 782  def test_feerate_checks_replaced_outputs(self, rbf_node, peer_node):
 783      # Make sure there is enough balance
 784      peer_node.sendtoaddress(rbf_node.getnewaddress(), 60)
 785      self.generate(peer_node, 1)
 786  
 787      self.log.info("Test that feerate checks use replaced outputs")
 788      outputs = []
 789      for i in range(50):
 790          outputs.append({rbf_node.getnewaddress(address_type="bech32"): 1})
 791      tx_res = rbf_node.send(outputs=outputs, fee_rate=5)
 792      tx_details = rbf_node.gettransaction(txid=tx_res["txid"], verbose=True)
 793  
 794      # Calculate the minimum feerate required for the bump to work.
 795      # Since the bumped tx will replace all of the outputs with a single output, we can estimate that its size will 31 * (len(outputs) - 1) bytes smaller
 796      tx_size = tx_details["decoded"]["vsize"]
 797      est_bumped_size = tx_size - (len(tx_details["decoded"]["vout"]) - 1) * 31
 798      inc_fee_rate = rbf_node.getmempoolinfo()["incrementalrelayfee"]
 799      # RPC gives us fee as negative
 800      min_fee = (-tx_details["fee"] + get_fee(est_bumped_size, inc_fee_rate)) * Decimal(1e8)
 801      min_fee_rate = (min_fee / est_bumped_size).quantize(Decimal("1.000"))
 802  
 803      # Attempt to bumpfee and replace all outputs with a single one using a feerate slightly less than the minimum
 804      new_outputs = [{rbf_node.getnewaddress(address_type="bech32"): 49}]
 805      assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx_res["txid"], {"fee_rate": min_fee_rate - 1, "outputs": new_outputs})
 806  
 807      # Bumpfee and replace all outputs with a single one using the minimum feerate
 808      rbf_node.bumpfee(tx_res["txid"], {"fee_rate": min_fee_rate, "outputs": new_outputs})
 809      self.clear_mempool()
 810  
 811  
 812  def test_bumpfee_with_feerate_ignores_walletincrementalrelayfee(self, rbf_node, peer_node):
 813      self.log.info('Test that bumpfee with fee_rate ignores walletincrementalrelayfee')
 814      # Make sure there is enough balance
 815      peer_node.sendtoaddress(rbf_node.getnewaddress(), 2)
 816      self.generate(peer_node, 1)
 817  
 818      dest_address = peer_node.getnewaddress(address_type="bech32")
 819      tx = rbf_node.send(outputs=[{dest_address: 1}], fee_rate=2)
 820  
 821      # Ensure you can not fee bump with a fee_rate below or equal to the original fee_rate
 822      assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx["txid"], {"fee_rate": 1})
 823      assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx["txid"], {"fee_rate": 2})
 824  
 825      # Ensure you can not fee bump if the fee_rate is more than original fee_rate but the additional fee does
 826      # not cover incrementalrelayfee for the size of the replacement transaction
 827      assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx["txid"], {"fee_rate": 2.09})
 828  
 829      # You can fee bump as long as the new fee set from fee_rate is at least (original fee + incrementalrelayfee)
 830      rbf_node.bumpfee(tx["txid"], {"fee_rate": 2.1})
 831      self.clear_mempool()
 832  
 833  
 834  if __name__ == "__main__":
 835      BumpFeeTest(__file__).main()
 836