gui: Use PSBT v0 #36539

pull davidgumberg wants to merge 2 commits into bitcoin:master from davidgumberg:2026-10-15-psbt-gui changing 8 files +24 −10
  1. davidgumberg commented at 8:18 AM on October 15, 2026: contributor

    This fixes: #36518

    There is no test added here for the bump fee PSBT's being v0, since there aren't any existing tests for watch only wallet feebumping in the GUI. If reviewers insist on this I can add it, but I wanted to keep the diff minimal. I have tested this manually.

    AFAIU for the external signer stuff it shouldn't matter much whether it's v0 or v2, since users are very unlikely to be using HWI software that doesn't speak v0, but out of caution I've set the external signer PSBT to v0 for the GUI.

    This PR originally took the approach of adding a checkbox, (davidgumberg/gui/2026-10-15-psbt-gui), but this was dropped to simplify backporting past string freeze.

    LLM Disclosure: The previous approach was drafted using an LLM, but this branch was written by me. I used an LLM to explore adding a fee bump watchonly GUI test, and decided against it.

  2. DrahtBot added the label GUI on Oct 15, 2026
  3. DrahtBot commented at 8:18 AM on October 15, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    ACK Sjors, w0xlt

    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:

    • #35511 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35511.svg"></sub> (RFC: consensus: Make CAmount a class by hodlinator)
    • #35302 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35302.svg"></sub> (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-->

  4. fanquake added this to the milestone 32.0 on Oct 15, 2026
  5. davidgumberg commented at 12:53 AM on October 16, 2026: contributor
  6. achow101 commented at 1:12 AM on October 16, 2026: member

    I don't think we should be adding any GUI elements for a PR targeting a backport, particularly as it adds strings for translation. We can do v0 only in the GUI I guess.

  7. fanquake commented at 4:45 AM on October 16, 2026: member
  8. Sjors commented at 8:13 AM on October 17, 2026: member

    We can do v0 only in the GUI I guess.

    That seems fine for now if it's easier. There could be a (release) note to use the RPC for v2 when needed.

  9. davidgumberg force-pushed on Oct 18, 2026
  10. davidgumberg renamed this:
    gui: Make PSBT version toggleable: v0 by default
    gui: Use PSBT v0
    on Oct 18, 2026
  11. davidgumberg commented at 11:11 PM on October 18, 2026: contributor

    I've pushed so that the GUI just returns v0 PSBT's.

  12. Sjors commented at 2:41 AM on October 20, 2026: member

    Code review f0777e68550cc100ab0341515c5c34bac45fc7a4.

    AFAIU for the external signer stuff it shouldn't matter much whether it's v0 or v2, since users are very unlikely to be using HWI software that doesn't speak v0, but out of caution I've set the external signer PSBT to v0 for the GUI.

    I think it's better to consistently use v2 for external signers, both from the GUI and RPC.

  13. in src/wallet/feebumper.cpp:345 in f0777e6855 outdated
     339 | @@ -340,8 +340,9 @@ bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
     340 |      LOCK(wallet.cs_wallet);
     341 |  
     342 |      if (wallet.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
     343 | -        // Make a blank psbt
     344 | -        PartiallySignedTransaction psbtx(mtx);
     345 | +        // Make a blank PSBT, this means that users will need to have an
     346 | +        // external signer software that supports BIP-0370.
     347 | +        PartiallySignedTransaction psbtx(mtx, /*version=*/2);
    


    Sjors commented at 2:43 AM on October 20, 2026:

    You can use the same comment in the regular send path, if you take my suggestion above.


    davidgumberg commented at 4:27 PM on October 26, 2026:

    Taken, thanks

  14. w0xlt commented at 5:15 PM on October 20, 2026: contributor

    The GUI fee bump with an external signer still uses v2 (WalletModel::bumpFee -> signBumpTransaction -> feebumper::SignTransaction, pinned to v2 and shared with RPC bumpfee).

    Suggestion: a psbt_version param can be added to feebumper::SignTransaction/signBumpTransaction, with the GUI passing 0 and RPC keeping 2.

    <details> <summary>diff</summary>

    diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
    index 8862f94fab..da140f721e 100644
    --- a/src/interfaces/wallet.h
    +++ b/src/interfaces/wallet.h
    @@ -175,7 +175,7 @@ public:
             CMutableTransaction& mtx) = 0;
     
         //! Sign bump transaction.
    -    virtual bool signBumpTransaction(CMutableTransaction& mtx) = 0;
    +    virtual bool signBumpTransaction(CMutableTransaction& mtx, uint32_t psbt_version) = 0;
     
         //! Commit bump transaction.
         virtual bool commitBumpTransaction(const Txid& txid,
    diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
    index 2422b88579..95454e2265 100644
    --- a/src/qt/walletmodel.cpp
    +++ b/src/qt/walletmodel.cpp
    @@ -524,7 +524,7 @@ bool WalletModel::bumpFee(Txid hash, Txid& new_hash)
         assert(!m_wallet->privateKeysDisabled() || wallet().hasExternalSigner());
     
         // sign bumped transaction
    -    if (!m_wallet->signBumpTransaction(mtx)) {
    +    if (!m_wallet->signBumpTransaction(mtx, /*psbt_version=*/0)) {
             QMessageBox::critical(nullptr, tr("Fee bump error"), tr("Can't sign transaction."));
             return false;
         }
    diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
    index ab64fd8cda..1c7288aedd 100644
    --- a/src/wallet/feebumper.cpp
    +++ b/src/wallet/feebumper.cpp
    @@ -336,13 +336,12 @@ Result CreateRateBumpTransaction(CWallet& wallet, const Txid& txid, const CCoinC
         return Result::OK;
     }
     
    -bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx) {
    +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx, uint32_t psbt_version) {
         LOCK(wallet.cs_wallet);
     
         if (wallet.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
    -        // Make a blank PSBT, this means that users will need to have an
    -        // external signer software that supports BIP-0370.
    -        PartiallySignedTransaction psbtx(mtx, /*version=*/2);
    +        // Make a blank psbt
    +        PartiallySignedTransaction psbtx(mtx, psbt_version);
     
             // First fill transaction with our data without signing,
             // so external signers are not asked to sign more than once.
    diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
    index 4e0befe412..62faea52af 100644
    --- a/src/wallet/feebumper.h
    +++ b/src/wallet/feebumper.h
    @@ -58,9 +58,10 @@ Result CreateRateBumpTransaction(CWallet& wallet,
         std::optional<uint32_t> original_change_index = std::nullopt);
     
     //! Sign the new transaction,
    +//! [@param](/github-metadata-backup-bitcoin-bitcoin/contributor/param/) psbt_version PSBT version passed to an external signer, if the wallet uses one
     //! [@return](/github-metadata-backup-bitcoin-bitcoin/contributor/return/) false if the tx couldn't be found or if it was
     //! impossible to create the signature(s)
    -bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx);
    +bool SignTransaction(CWallet& wallet, CMutableTransaction& mtx, uint32_t psbt_version);
     
     //! Commit the bumpfee transaction.
     //! [@return](/github-metadata-backup-bitcoin-bitcoin/contributor/return/) success in case of CWallet::CommitTransaction was successful,
    diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp
    index a7d24ca0b9..3a70e88c3a 100644
    --- a/src/wallet/interfaces.cpp
    +++ b/src/wallet/interfaces.cpp
    @@ -300,7 +300,7 @@ public:
             std::vector<CTxOut> outputs; // just an empty list of new recipients for now
             return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx, /* require_mine= */ true, outputs) == feebumper::Result::OK;
         }
    -    bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); }
    +    bool signBumpTransaction(CMutableTransaction& mtx, uint32_t psbt_version) override { return feebumper::SignTransaction(*m_wallet.get(), mtx, psbt_version); }
         bool commitBumpTransaction(const Txid& txid,
             CMutableTransaction&& mtx,
             std::vector<bilingual_str>& errors,
    diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
    index e228298c0c..9de3464675 100644
    --- a/src/wallet/rpc/spend.cpp
    +++ b/src/wallet/rpc/spend.cpp
    @@ -1138,7 +1138,8 @@ static RPCMethod bumpfee_helper(std::string method_name)
         // For bumpfee, return the new transaction id.
         // For psbtbumpfee, return the base64-encoded unsigned PSBT of the new transaction.
         if (!want_psbt) {
    -        if (!feebumper::SignTransaction(*pwallet, mtx)) {
    +        // External signers must support BIP-0370 (PSBT v2)
    +        if (!feebumper::SignTransaction(*pwallet, mtx, /*psbt_version=*/2)) {
                 if (pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) {
                     throw JSONRPCError(RPC_WALLET_ERROR, "Transaction incomplete. Try psbtbumpfee instead.");
                 }
    

    </details>

  15. fanquake removed this from the milestone 32.0 on Oct 21, 2026
  16. fanquake added this to the milestone 32.1 on Oct 21, 2026
  17. fanquake added the label Needs Backport (32.x) on Oct 21, 2026
  18. fanquake commented at 11:07 AM on October 21, 2026: member

    Pushed this to the 32.1 milestone.

  19. fanquake removed this from the milestone 32.1 on Oct 26, 2026
  20. fanquake added this to the milestone 32.2 on Oct 26, 2026
  21. davidgumberg force-pushed on Oct 26, 2026
  22. gui: wallet: Use v0 PSBT
    PSBTv2 is not very interesting for current GUI users, and defaulting to
    it causes issues for existing users. To make this change minimal and
    avoid touching strings, this commit, only changes the default back
    instead of making the version configurable.
    
    The external signer PSBT will still be version 2, and I've added an
    explicit argument here to show that. This will break users who are using
    HWI versions < 2.1.0.
    (https://github.com/bitcoin-core/HWI/releases/tag/2.1.0)
    23dcb03a2c
  23. refactor: psbt: Don't set a default version for PSBT constructor 3fdc45d1fa
  24. davidgumberg force-pushed on Oct 26, 2026
  25. davidgumberg commented at 4:26 PM on October 26, 2026: contributor

    I've modified this so that the external signer PSBT's are v2, this breaks support with external signer software that doesn't know about v2, which is quite reasonable I think, so I've added a release note about that.

  26. DrahtBot added the label CI failed on Oct 26, 2026
  27. Sjors commented at 12:24 PM on October 27, 2026: member

    ACK 3fdc45d1fa2a6f32f251aa6f639a52bbfd5245b0

    Sadly we missed the 32.1 milestone, time flies.

  28. hebasto commented at 1:57 PM on October 27, 2026: member

    I've re-run previously cancelled CI jobs.

  29. DrahtBot removed the label CI failed on Oct 27, 2026
  30. w0xlt commented at 7:59 PM on October 27, 2026: contributor

    crACK 3fdc45d1fa2a6f32f251aa6f639a52bbfd5245b0


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-10-30 09:40 UTC