wallet: deprecate replaceable argument from transaction (and psbt) creation (and modification) RPCs #35433

pull rkrux wants to merge 9 commits into bitcoin:master from rkrux:deprecaterbf changing 15 files +172 −68
  1. rkrux commented at 3:03 PM on June 1, 2026: contributor

    Fixes #32661.

    The replaceable argument in several wallet RPC requests has been marked deprecated and for now users have the option to use this argument via the -deprecatedrpc=bip125 startup option. Affected RPCs are createrawtransaction, fundrawtransaction, createpsbt, walletcreatefundedpsbt, send, sendtoaddress, sendmany, sendall, bumpfee, and psbtbumpfee.

    This builds upon the existing issue of removing the option for users to signal replaceability because fullrbf is the default policy and prevalent in the network (since bitcoin core v28 was released in late 2024) that makes every transaction replaceable by default, making this user option unnecessary.

  2. DrahtBot commented at 3:04 PM on June 1, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35433.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK polespinasa

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35358 (external signer: verify PSBT is reliable after signing it by brunoerg)
    • #35302 (Silent Payments: Sending (take 2) by Eunovo)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible places where named args for integral literals may be used (e.g. func(x, /*named_arg=*/0) in C++, and func(x, named_arg=0) in Python):

    • self.nodes[0].createrawtransaction([], {}, 0, None, TX_MIN_STANDARD_VERSION - 1) in test/functional/rpc_rawtransaction.py
    • self.nodes[0].createrawtransaction([], {}, 0, None, TX_MAX_STANDARD_VERSION + 1) in test/functional/rpc_rawtransaction.py
    • node.createrawtransaction(inputs, outputs, 0) in test/functional/wallet_balance.py
    • wallet.createrawtransaction([], {target_address: 0.1}, 0) in test/functional/wallet_fundrawtransaction.py
    • mock_wallet.walletcreatefundedpsbt([], {dest:0.5}, 0, {}, True) in test/functional/wallet_signer.py
    • self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height+2, {"add_inputs": True}, False) in test/functional/rpc_psbt.py
    • self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}], block_height, {"add_inputs": True}, True) in test/functional/rpc_psbt.py

    <sup>2026-07-07 11:46:09</sup>

  3. rkrux commented at 3:08 PM on June 1, 2026: contributor

    I will add test case for bumpfee and psbtbumpfee along with release note.

  4. rkrux renamed this:
    Deprecaterbf
    wallet: deprecate replaceable argument from transaction ( and psbt) creation (and modification) RPCs
    on Jun 1, 2026
  5. DrahtBot added the label Wallet on Jun 1, 2026
  6. rkrux renamed this:
    wallet: deprecate replaceable argument from transaction ( and psbt) creation (and modification) RPCs
    wallet: deprecate replaceable argument from transaction (and psbt) creation (and modification) RPCs
    on Jun 1, 2026
  7. DrahtBot added the label CI failed on Jun 1, 2026
  8. DrahtBot commented at 4:29 PM on June 1, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task lint: https://github.com/bitcoin/bitcoin/actions/runs/26763283466/job/78882570147</sub> <sub>LLM reason (✨ experimental): CI failed because the Python lint (ruff) reported an error—an unused import MAX_BIP125_RBF_SEQUENCE in test/functional/rpc_psbt.py.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  9. rkrux force-pushed on Jun 2, 2026
  10. rkrux commented at 10:03 AM on June 2, 2026: contributor

    I will add test case for bumpfee and psbtbumpfee along with release note.

    Done now.

  11. rkrux force-pushed on Jun 2, 2026
  12. rkrux force-pushed on Jun 2, 2026
  13. rkrux force-pushed on Jun 2, 2026
  14. rkrux force-pushed on Jun 2, 2026
  15. rkrux force-pushed on Jun 2, 2026
  16. DrahtBot removed the label CI failed on Jun 2, 2026
  17. rkrux force-pushed on Jun 5, 2026
  18. rkrux commented at 11:01 AM on June 5, 2026: contributor

    Updated the PR to not depend on #35405, removed the two commit from that PR.

  19. rkrux marked this as ready for review on Jun 5, 2026
  20. rkrux commented at 12:14 PM on June 10, 2026: contributor

    Pushed the last two testing related commits of PR #35442 here as per this review comment #35442 (comment).

    Edit: Reverted as they are dependent on #35405 as well slightly.

  21. rkrux force-pushed on Jun 10, 2026
  22. DrahtBot added the label CI failed on Jun 10, 2026
  23. DrahtBot commented at 12:21 PM on June 10, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task lint: https://github.com/bitcoin/bitcoin/actions/runs/27275445645/job/80555467804</sub> <sub>LLM reason (✨ experimental): CI failed because Python linting reported an error: test_framework.messages is missing MAX_BIP125_RBF_SEQUENCE in test/functional/rpc_psbt.py.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  24. DrahtBot removed the label CI failed on Jun 10, 2026
  25. pablomartin4btc commented at 7:31 PM on June 12, 2026: member

    Edit: Reverted as they are dependent on #35405 as well slightly.

    I think the PR's description needs to be updated again?

  26. in doc/release-notes-34917.md:1 in db831dbde6
       0 | @@ -1,9 +1,23 @@
       1 |  RPC and Startup Option
    


    pablomartin4btc commented at 7:45 PM on June 12, 2026:

    as per #35405...

    Wallet RPC and Startup Option
    

    rkrux commented at 7:51 AM on June 15, 2026:

    Done.

  27. rkrux force-pushed on Jun 15, 2026
  28. rkrux commented at 7:54 AM on June 15, 2026: contributor

    Edit: Reverted as they are dependent on #35405 as well slightly.

    I think the PR's description needs to be updated again?

    The description is fine, it was written before these two commits (now removed) were added in this PR.

  29. rkrux force-pushed on Jun 15, 2026
  30. DrahtBot added the label CI failed on Jun 15, 2026
  31. rkrux commented at 8:44 AM on June 15, 2026: contributor

    Force-pushed to not hardcode replaceable as false in the RPC help sections and CCoinControl objects. Based on the feedback on PR #35405 and the corresponding responses in the ML.

  32. rkrux force-pushed on Jun 15, 2026
  33. rkrux force-pushed on Jun 15, 2026
  34. rkrux commented at 9:03 AM on June 15, 2026: contributor

    Force-pushed to update the rpc_psbt.py test that failed after reverting the default replaceable value to true in createpsbt RPC.

  35. rkrux commented at 9:18 AM on June 15, 2026: contributor
  36. in src/wallet/spend.cpp:1304 in ac6ad606d1


    maflcko commented at 10:55 AM on June 15, 2026:

    ac6ad606d1a10ed9f30433e6d6f038c3a2e39cab: This seems to be the wrong commit/change. It marks the comment why maxint-2 was chosen as deprecated. However, the code here doesn't use a maxint-2 int literals. Instead, the comment should be moved to MAX_BIP125_RBF_SEQUENCE, which picks the int literal.

    In this commit, I guess you wanted to mark m_signal_bip125_rbf or m_signal_rbf as deprecated? If so, it would be better to put the comment change there.


    rkrux commented at 12:28 PM on June 15, 2026:

    Instead, the comment should be moved to MAX_BIP125_RBF_SEQUENCE, which picks the int literal.

    Moved in rbf.h, it does look better as the comment becomes the documentation for this constant highlighting that this value is deprecated/outdated.


    maflcko commented at 1:29 PM on June 15, 2026:

    Sorry, I think I was unclear. What I wanted to say was that the change seems to be unrelated (to this pull request, as well as this commit), so at a minimum, it should be split into a separate commit.

    Marking MAX_BIP125_RBF_SEQUENCE as deprecated is done in #35405, so if that pull request is closed, it doesn't make sense to mark it as deprecated, because it will stay around.

    Also, MAX_BIP125_RBF_SEQUENCE is used in more RPC than just bumpfee, so bundling this change in the commit that changes bumpfee doesn't really make sense.

    So I think this change should be split into a separate commit


    rkrux commented at 2:35 PM on June 15, 2026:

    What I wanted to say was that the change seems to be unrelated (to this pull request, as well as this commit), so at a minimum, it should be split into a separate commit.

    Yeah, it does seem to be a remnant of an outdated version of this PR that was built over #34505.

    Marking MAX_BIP125_RBF_SEQUENCE as deprecated is done in #35405, so if that pull request is closed, it doesn't make sense to mark it as deprecated, because it will stay around.

    Not marked it deprecated now. Maybe later in #35442 when I rework it, let's see.

    Also, MAX_BIP125_RBF_SEQUENCE is used in more RPC than just bumpfee, so bundling this change in the commit that changes bumpfee doesn't really make sense. So I think this change should be split into a separate commit

    Yes, this makes sense. I have separated it out now.


    polespinasa commented at 2:19 PM on July 7, 2026:

    In 3ac9c24124f0722649016a12fdf39eb9a628cd94 wallet, rpc: deprecate replaceable argument in bumpfee, psbtbumpfee RPCs

    ~This stills wrong, this PR does not introduce the error, but m_signal_bip125_rbf is an optional, if it is not set, it will set it to true, but if it is explicitly set to false it will be overwritten to true anyway. It should be if (!cc.m_signal_bip125_rbf.has_value())~

    Nevermind, I just got confused, it does not make sense, feel free to resolve the conversation


    rkrux commented at 2:31 PM on July 7, 2026:

    this PR does not introduce the error

    This should be addressed in a separate PR.

  37. rkrux force-pushed on Jun 15, 2026
  38. DrahtBot removed the label CI failed on Jun 15, 2026
  39. rkrux force-pushed on Jun 15, 2026
  40. DrahtBot added the label CI failed on Jun 15, 2026
  41. DrahtBot commented at 4:44 PM on June 15, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task iwyu: https://github.com/bitcoin/bitcoin/actions/runs/27553730406/job/81452610641</sub> <sub>LLM reason (✨ experimental): CI failed because IWYU detected missing/incorrect #includes (failure generated from IWYU) in src/bench/pool.cpp.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  42. rkrux commented at 6:59 AM on June 16, 2026: contributor

    The CI / iwyu (pull_request) failure is unrelated and should have been fixed post #35535.

  43. DrahtBot removed the label CI failed on Jun 16, 2026
  44. achow101 referenced this in commit 93012d7ff9 on Jun 25, 2026
  45. DrahtBot added the label Needs rebase on Jun 26, 2026
  46. wallet, util: move BIP-125 related comment to util/rbf.h from wallet/spend.cpp
    This comment is an explanation for why such a value was chosen in
    the now outdated BIP-125 opt-in signalling flow, so moving it to where
    this constant is defined seems more appropriate instead of it being present
    deep in a nested transaction creation flow in the wallet.
    
    It also serves as a documentation for this constant now, which is helpful.
    d1ba4390e1
  47. rkrux force-pushed on Jun 27, 2026
  48. rkrux commented at 7:36 AM on June 27, 2026: contributor

    Rebased over master to incorporate changes from PR #35543.

  49. DrahtBot removed the label Needs rebase on Jun 27, 2026
  50. in src/wallet/rpc/spend.cpp:231 in 85df2740b1
     227 | @@ -228,7 +228,7 @@ static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const Un
     228 |          cc.m_feerate = CFeeRate{AmountFromValue(fee_rate, /*decimals=*/3)};
     229 |          if (override_min_fee) cc.fOverrideFeeRate = true;
     230 |          // Default RBF to true for explicit fee_rate, if unset.
     231 | -        if (!cc.m_signal_bip125_rbf) cc.m_signal_bip125_rbf = true;
     232 | +        if (!cc.m_signal_bip125_rbf) cc.m_signal_bip125_rbf = DEFAULT_WALLET_RBF;
    


    polespinasa commented at 4:58 PM on July 6, 2026:

    in 85df2740b1e2cd6c7ca3e3d19180e707373244ee wallet, rpc: deprecate replaceable argument in bumpfee, psbtbumpfee RPCs

    This looks wrong, should be !cc.m_signal_bip125_rbf.hasValue(). As it is if it has value and the value if false it will be overwritten to DEFAULT_WALLET_RBF


    achow101 commented at 8:15 PM on July 6, 2026:

    It should also still be using true, not be changed to DEFAULT_WALLET_RBF as the idea is to unconditionally set it to true, not use the default for the wallet.


    rkrux commented at 11:45 AM on July 7, 2026:

    Reverted

  51. in test/functional/wallet_deprecated_rbf.py:58 in 020560e00a
      56 | +                              self.nodes[0].createrawtransaction, [{'txid': unspent["txid"], 'vout': unspent["vout"], 'sequence': MAX_BIP125_RBF_SEQUENCE+1}], {}, 0, True)
      57 | +
      58 | +      raw_tx_hex = wallet.createrawtransaction(inputs=[unspent], outputs=[{wallet.getnewaddress(): 1}], replaceable=True)
      59 | +      assert_rbf_in_tx_hex(raw_tx_hex)
      60 | +      funded_tx_hex = wallet.fundrawtransaction(raw_tx_hex)["hex"]
      61 | +      assert_rbf_in_tx_hex(raw_tx_hex)
    


    polespinasa commented at 5:00 PM on July 6, 2026:

    in 020560e00a4b49e5ceb4365def4f2e07b60eee57 wallet, test: add test cases for deprecated RBF features

    Should be assert_rbf_in_tx_hex(funded_tx_hex) ??


    rkrux commented at 11:45 AM on July 7, 2026:

    Fixed

  52. in test/functional/wallet_deprecated_rbf.py:5 in 020560e00a outdated
       1 | @@ -2,8 +2,9 @@
       2 |  # Copyright (c) 2026-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 deprecation of RPC calls."""
       6 | -from test_framework.util import assert_equal
       7 | +"""Test deprecation of wallet RBF RPCs and startup options."""
    


    polespinasa commented at 5:02 PM on July 6, 2026:

    in 020560e00a4b49e5ceb4365def4f2e07b60eee57 wallet, test: add test cases for deprecated RBF features

    nit: we use 4 spaces for indentation, this test uses 3.

  53. polespinasa commented at 5:05 PM on July 6, 2026: member

    concept ACK

    reviewed 020560e00a4b49e5ceb4365def4f2e07b60eee57

    The code looks good, but I think the way it is done the deprecation might be invisible for the users. If a user does add a replaceable argument but does not enable the deprecated flag it will be ignored without the user noticing.

    I think all deprecated fields should throw if used when the deprecated flag is not set.

    in 020560e00a4b49e5ceb4365def4f2e07b60eee57 wallet, test: add test cases for deprecated RBF features The test only checks the replaceable=True, does not check for replaceable=False.

  54. in src/wallet/rpc/spend.cpp:1050 in 85df2740b1
    1046 | @@ -1047,7 +1047,7 @@ static RPCMethod bumpfee_helper(std::string method_name)
    1047 |  
    1048 |      CCoinControl coin_control;
    1049 |      // optional parameters
    1050 | -    coin_control.m_signal_bip125_rbf = true;
    1051 | +    coin_control.m_signal_bip125_rbf = DEFAULT_WALLET_RBF;
    


    achow101 commented at 8:16 PM on July 6, 2026:

    In 85df2740b1e2cd6c7ca3e3d19180e707373244ee "wallet, rpc: deprecate replaceable argument in bumpfee, psbtbumpfee RPCs"

    This should not be changed


    rkrux commented at 11:45 AM on July 7, 2026:

    Reverted

  55. in doc/release-notes-34917.md:1 in c2515fc66f
       0 | @@ -1,9 +1,23 @@
       1 | -RPC and Startup Option
       2 | +Wallet RPC and Startup Option
    


    achow101 commented at 8:19 PM on July 6, 2026:

    In c2515fc66fb5b91dce6552e79286b6117dbd68df "doc: update release notes of 34917 mentioning replaceable deprecation"

    This is not a valid section header for release notes.

    This could either be a standalone Notable Change, in which case this section header should be a title that describes what the change, or it should be one of the standard section headers in doc/release-notes-empty-template.md (i.e. Wallet)


    rkrux commented at 11:45 AM on July 7, 2026:

    Fixed

  56. achow101 commented at 8:37 PM on July 6, 2026: member

    a00899f3d7fca8ed5d8f849bca4979099a3d8aac "wallet, test: replace rbf_node with node in wallet_bumpfee.py" seems entirely unnecessary. Mass renaming things in that file breaks git blame, and I don't really see the benefit for changing the name. rbf_node is still kind of appropriate because that's node that's doing all of the rbf things.

    The deprecation should be throwing if the option is set, not silently ignoring it. For the options objects, it can throw if the option is provided at all. For positional arguments, the argument must be null. We only accept the option if -deprecatedrpc is provided.

  57. wallet, rpc: deprecate replaceable argument in bumpfee, psbtbumpfee RPCs 3ac9c24124
  58. wallet, rpc: deprecate replaceable argument in sendall RPC 5d6fff2c01
  59. wallet, rpc: deprecate replaceable argument in walletcreatefundedpsbt, fundrawtransaction 9e08a7e78d
  60. wallet, rpc: deprecate replaceable argument in send RPC e40bd9163b
  61. wallet, rpc: deprecate replaceable argument in sendtoaddress, sendmany RPCs 1b8df68f95
  62. rpc: deprecate replaceable argument in createrawtransaction, createpsbt ce6d0dcb11
  63. wallet, test: add test cases for deprecated RBF features
    Tested RPCs: createrawtransaction, fundrawtransaction, createpsbt, bumpfee
    walletcreatefundedpsbt, send, sendtoaddress, sendmany, sendall, psbtbumpfee.
    caae1595cf
  64. doc: update release notes of 34917 mentioning `replaceable` deprecation 8bd077ae9d
  65. rkrux force-pushed on Jul 7, 2026
  66. rkrux commented at 11:45 AM on July 7, 2026: contributor

    I think all deprecated fields should throw if used when the deprecated flag is not set.

    Done

    in https://github.com/bitcoin/bitcoin/commit/020560e00a4b49e5ceb4365def4f2e07b60eee57 wallet, test: add test cases for deprecated RBF features The test only checks the replaceable=True, does not check for replaceable=False.

    Done

    https://github.com/bitcoin/bitcoin/commit/a00899f3d7fca8ed5d8f849bca4979099a3d8aac "wallet, test: replace rbf_node with node in wallet_bumpfee.py" seems entirely unnecessary. Mass renaming things in that file breaks git blame, and I don't really see the benefit for changing the name. rbf_node is still kind of appropriate because that's node that's doing all of the rbf things.

    Dropped

    The deprecation should be throwing if the option is set, not silently ignoring it. For the options objects, it can throw if the option is provided at all. For positional arguments, the argument must be null. We only accept the option if -deprecatedrpc is provided.

    Done


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-07-09 06:47 UTC